Maven搭建SpringWebService(1)
2014-11-30 15:25
288 查看
此文是写给像我这样的菜鸟的,所以比较简单,大神可以略过。
我做过的项目基本上都使用的CXF或AXIS搭建WebService。SpringWebService(以下简写为SWS)是我这几天一直在琢磨学习的,可是第一步完成一个Demo就难住我了。经过几天空余时间不懈的努力。终于完成了这个Demo。
使用工具:Eclipse4.4,JDK7,Tomcat7,Maven3
第一步:在Eclipse中构建一个Mevan的Web项目,项目结构如下:
第二步:项目中pom配置,配置如下:
以上2步完成了基本环境的搭建,下面开始编写SWS。
SWS区别于CXF,AXIS之一就是在于,我之前做的项目服务端WS的编写都是从代码开始的,而SWS是从数据描述开始的,也就是先编写XML,这里的XML指XSD文件,即XML Schema文件,与DTD文件的作用类似,都是用来描述XML文档结构的。不过直接编写XSD文件还是有点难度的,好在我们有很多工具帮助我们通过XML数据文件反向生成XSD文件。换句话说,我们如果需要给两个系统做一个WS,我们可以先写一个2个系统都可以解析的XML数据文件。例如我现在有个2个系统。分别叫用户管理系统(以下叫A系统),另一个是财务系统(以下叫B系统),假设B系统每次新增用户的时候也需要在A系统中增加相同用户。(这个例子肯定不符合生产系统的需求,这里只是举例做一个Demo)。
我们现在编写AB两个系统都可以解析的XML数据文件,如下:
我们现在就可以根据上面的XML文档反向生成XSD文件。我们可以借助工具生成,如XMLSpy,这个工具很强大,至于有多强大,我也不是很清楚,只是周围的人用的很多。
这里我是通过Trang Manual这个jar生成XSD文件的。
Trang Manual官网:http://www.thaiopensource.com/relaxng/trang.html 在此页面个Download区域下载此jar的zip文件。
下载解压,请记住自己的解压路径。
这里有个前提是,自己已经将java环境搭建好了,不知道自己是否搭建好了java环境,window下请在命令行cmd下运行java -version。linux/macos请在terminal下执行此命令,如果可以看到自己配置的jdk版本信息,就证明java环境变量已经设置好了。
假设:我们将上面的xml数据示例文件保存在某个文件夹下,并给文件起名叫AddUser.xml,现在我们在命令行下运行以下命令:
我这里是在maxos下执行的,windows下请将上面命令中的路径换为windows路径即可。如果想知道tang.jar后的参数意义,可执行:
假设你xml文件没有问题,且命令正确,执行完以上命令后你会看不到任何信息反馈,证明生成XSD文件成功(没有消息就是最好的消息)。因为上面命令将输出路径设置为同路径下,所以我在刚才的AddUser.xml文件所在文件夹下就可以看到生成的XSD文件。如下:
现在我们需要对上面生成的文件做一些修改,如生成的数据类型:xs:NCName,修改为xs:string。并将prefix前缀schema:修改为ws(修改这里时,需要修改xs:根属性中的xslns:schema为xmlns:ws):,修改完毕后如下:
到这一步时,SWS的前置工作就做完了,现在我们就可以在之前创建的maven的web项目中开始写我们的第一个webservice了。
(XSD的相关内容,大家可以查看W3CSchool中的教程,URL:http://www.w3school.com.cn/schema/index.asp)
maven的web项目结构我就不具体解释了,因为相关教程文章很多。
我在java/resources文件夹下创建的V1文件夹,并将上面生成的AddUser.xsd文件放在此文件夹下,V1文件夹不是必须的,你也可以直接放在resources文件夹下。只不过如果同一个接口有多版本共存时,使用文件夹划分我觉得比较好一些。比如V2文件夹可以存放AddUser.xsd文件的第二版本。这样的划分也是我参考别的教程中的。觉得这样做的确比较好一些。
接下来配置项目中的web.xml文件,SWS的配置与SF框架的配置类似。配置如下:
MessageDispatcherServlet类似SpringMVC中的DispatcherServlet,是它的子类,用于处理SOAP请求,将请求转发给对应的服务端点(即我们后面用到的注解@Endpoint)。
我们在web.xml同文件夹下创建ws-servlet.xml文件。因为我们在web.xml文件内使用ws起的servlet名称,所以此文件就叫ws-servlet.xml,如果你在web.xml中起名是其他,那么此文件就换为名称-servlet.xml。这里的配置如下:
这里我的见解是:ws-servlet.xml中的配置是为了对外发布WSDL文档。
这里我们还剩下最后一步:编写服务端端点代码,SWS框架提供了很多对SOAP消息解析的接口,也就是说我们可以选择我们喜欢的方式解析SOAP消息内容。这里我使用XPath对消息进行解析。代码如下:
加载项目至tomcat7中,配置无误的话,启动应该是成功的。
在浏览器下输入我们的URL:http://localhost:8080/dmsws/AddUserService.wsdl,如果一切配置正确,此时你会看到我们对外发布的WSDL文件信息。
(请在外置浏览器下查看此链接地址,之前我在eclipse的内置浏览器下访问,页面没有任何显示。一片空白,调试了好久,查不到问题,还以为自己哪里配置错了,最后无意识的再外面浏览器下访问,WSDL文件就直接出来了)
如果我们这一步不编写服务端点的java类,只做到ws-servlet.xml配置的哪一步,wsdl文档是否可以生成呢?答案是可以。wsdl文档生成并不依赖我们编写的服务端代码,如AddUserEndpoint类。SWS框架通过我们配置声明的DefaultWsdl11Definition类及下面的参数(如XSD文件等)自动帮我们动态生成WSDL文件。
WSDL文件只是告诉客户端如何访问我们提供的WebService,而我们编写的Endpoint类是具体服务的实现。举个例子ws-servlet.xml就做菜的食材,而我们编写的Endpoint类是食材加工厂,可以对“传来”的食材进行加工,至于怎么加工,就是我们编写的方法内容了。所以二者缺一不可。
以上是服务端的编写内容。我在编写此Demo是遇到了不少问题,所以查了不少资料,主要参考了SWS官网的Doc文档,还有Spring3.X企业应用开发实战的附录内容,还有网上的一些其他Demo。但都有一些问题。希望这边文章可以帮助跟我一样遇到问题的人。
服务端生成了,现在还缺少客户端代码。下面使用JDK的wsimport命令生成客户端代码并进行测试。
JDK命令如下:
wsimport -d ./ -keep -verbose http://localhost:8080/dmsws/service/AddUserService.wsdl-d后面是代码生成后的保存路径,-verbose是显示生成过程的信息,-keep是为了生成.java文件。
参数正确的话,就可以在指定目录看到生成的java文件,我们将此文件Copy至任意EclipseJava工程下,为了简单,我直接将生成的文件(包含文件夹)copy至我们的SWS的demo项目,如下:
根据我们生成的工具类,我们就可以编写测试客户端代码了,代码如下:
package com.org.dms.ws.client;
import java.math.BigInteger;
import com.dmsws.ws.schemas.AddUserPortType;
import com.dmsws.ws.schemas.AddUserPortTypeService;
import com.dmsws.ws.schemas.AddUserRequest;
import com.dmsws.ws.schemas.UserType;
public class ActionLogClient {
public static void main(String[] args) {
UserType user = new UserType();
user.setPwd("password1234");
user.setUserAge("16");
user.setUserName("fuxiao");
AddUserRequest request = new AddUserRequest();
request.setUser(user);
AddUserPortTypeService service = new AddUserPortTypeService();
AddUserPortType pt = service.getAddUserPortTypeSoap11();
BigInteger n = pt.addUser(request);
System.out.println(n);
}
}
直接执行main方法,我们就可以在服务端控制台下,看到请求内容,如下:
至此demo编写完毕。希望可以帮助到大家,谢谢。
(本人才疏学浅,如有有不正确的地方希望大家海涵。)
我做过的项目基本上都使用的CXF或AXIS搭建WebService。SpringWebService(以下简写为SWS)是我这几天一直在琢磨学习的,可是第一步完成一个Demo就难住我了。经过几天空余时间不懈的努力。终于完成了这个Demo。
使用工具:Eclipse4.4,JDK7,Tomcat7,Maven3
第一步:在Eclipse中构建一个Mevan的Web项目,项目结构如下:
第二步:项目中pom配置,配置如下:
<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.yonyou.dms</groupId> <artifactId>dmsws</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>dmsws Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-xml</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.3</version> </dependency> <dependency> <groupId>org.apache.ws.xmlschema</groupId> <artifactId>xmlschema-core</artifactId> <version>2.2.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> <finalName>dmsws</finalName> </build> </project>
以上2步完成了基本环境的搭建,下面开始编写SWS。
SWS区别于CXF,AXIS之一就是在于,我之前做的项目服务端WS的编写都是从代码开始的,而SWS是从数据描述开始的,也就是先编写XML,这里的XML指XSD文件,即XML Schema文件,与DTD文件的作用类似,都是用来描述XML文档结构的。不过直接编写XSD文件还是有点难度的,好在我们有很多工具帮助我们通过XML数据文件反向生成XSD文件。换句话说,我们如果需要给两个系统做一个WS,我们可以先写一个2个系统都可以解析的XML数据文件。例如我现在有个2个系统。分别叫用户管理系统(以下叫A系统),另一个是财务系统(以下叫B系统),假设B系统每次新增用户的时候也需要在A系统中增加相同用户。(这个例子肯定不符合生产系统的需求,这里只是举例做一个Demo)。
我们现在编写AB两个系统都可以解析的XML数据文件,如下:
<AddUserRequest xmlns="http://www.dmsws.com/ws/schemas"> <User> <UserName>fuxiao</UserName> <UserAge>18</UserAge> <Pwd>password1234</Pwd> </User> </AddUserRequest>
我们现在就可以根据上面的XML文档反向生成XSD文件。我们可以借助工具生成,如XMLSpy,这个工具很强大,至于有多强大,我也不是很清楚,只是周围的人用的很多。
这里我是通过Trang Manual这个jar生成XSD文件的。
Trang Manual官网:http://www.thaiopensource.com/relaxng/trang.html 在此页面个Download区域下载此jar的zip文件。
下载解压,请记住自己的解压路径。
这里有个前提是,自己已经将java环境搭建好了,不知道自己是否搭建好了java环境,window下请在命令行cmd下运行java -version。linux/macos请在terminal下执行此命令,如果可以看到自己配置的jdk版本信息,就证明java环境变量已经设置好了。
假设:我们将上面的xml数据示例文件保存在某个文件夹下,并给文件起名叫AddUser.xml,现在我们在命令行下运行以下命令:
java -jar ~/Downloads/trang-20030619/trang.jar -I xml -O xsd ./AddUser.xml ./AddUser.xsd
我这里是在maxos下执行的,windows下请将上面命令中的路径换为windows路径即可。如果想知道tang.jar后的参数意义,可执行:
java -jar ~/Downloads/trang-20030619/trang.jar之后为看到参数详解。
假设你xml文件没有问题,且命令正确,执行完以上命令后你会看不到任何信息反馈,证明生成XSD文件成功(没有消息就是最好的消息)。因为上面命令将输出路径设置为同路径下,所以我在刚才的AddUser.xml文件所在文件夹下就可以看到生成的XSD文件。如下:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.dmsws.com/ws/schemas" <span style="color:#ff6666;">xmlns:schemas</span>="http://www.dmsws.com/ws/schemas"> <xs:element name="AddUserRequest"> <xs:complexType> <xs:sequence> <xs:element ref="<span style="color:#ff6666;">schemas:User</span>"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="User"> <xs:complexType> <xs:sequence> <xs:element ref="<span style="color:#ff6666;">schemas:UserName</span>"/> <xs:element ref="<span style="color:#ff6666;">schemas:UserAge</span>"/> <xs:element ref="<span style="color:#ff6666;">schemas:Pwd</span>"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="UserName" type="<span style="color:#ff6666;">xs:NCName</span>"/> <xs:element name="UserAge" type="<span style="color:#ff6666;">xs:integer</span>"/> <xs:element name="Pwd" type="<span style="color:#ff6666;">xs:NCName</span>"/> </xs:schema>
现在我们需要对上面生成的文件做一些修改,如生成的数据类型:xs:NCName,修改为xs:string。并将prefix前缀schema:修改为ws(修改这里时,需要修改xs:根属性中的xslns:schema为xmlns:ws):,修改完毕后如下:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.dmsws.com/ws/schemas" xmlns:ws="http://www.dmsws.com/ws/schemas"> <xs:element name="AddUserRequest"> <xs:complexType> <xs:sequence> <xs:element name="User" type="ws:UserType" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="UserType"> <xs:sequence> <xs:element ref="ws:UserName"/> <xs:element ref="ws:UserAge"/> <xs:element ref="ws:Pwd"/> </xs:sequence> </xs:complexType> <xs:element name="UserName" type="xs:string"/> <xs:element name="UserAge" type="xs:string" /> <xs:element name="Pwd" type="xs:string" /> <xs:element name="AddUserResponse" type="xs:integer" /> </xs:schema>
到这一步时,SWS的前置工作就做完了,现在我们就可以在之前创建的maven的web项目中开始写我们的第一个webservice了。
(XSD的相关内容,大家可以查看W3CSchool中的教程,URL:http://www.w3school.com.cn/schema/index.asp)
maven的web项目结构我就不具体解释了,因为相关教程文章很多。
我在java/resources文件夹下创建的V1文件夹,并将上面生成的AddUser.xsd文件放在此文件夹下,V1文件夹不是必须的,你也可以直接放在resources文件夹下。只不过如果同一个接口有多版本共存时,使用文件夹划分我觉得比较好一些。比如V2文件夹可以存放AddUser.xsd文件的第二版本。这样的划分也是我参考别的教程中的。觉得这样做的确比较好一些。
接下来配置项目中的web.xml文件,SWS的配置与SF框架的配置类似。配置如下:
<!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:applicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>ws</servlet-name> <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ws</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ws</servlet-name> <url-pattern>*.wsdl</url-pattern> </servlet-mapping> </web-app>
MessageDispatcherServlet类似SpringMVC中的DispatcherServlet,是它的子类,用于处理SOAP请求,将请求转发给对应的服务端点(即我们后面用到的注解@Endpoint)。
我们在web.xml同文件夹下创建ws-servlet.xml文件。因为我们在web.xml文件内使用ws起的servlet名称,所以此文件就叫ws-servlet.xml,如果你在web.xml中起名是其他,那么此文件就换为名称-servlet.xml。这里的配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- WSDL定义 --> <bean id="AddUserService" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"> <property name="schemaCollection"> <bean id="forumSchemaCollection" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection"> <property name="xsds"> <list> <value>classpath:v1/adduser.xsd</value> </list> </property> <property name="inline" value="true" /> </bean> </property> <property name="schema"> <bean class="org.springframework.xml.xsd.SimpleXsdSchema"> <property name="xsd" value="classpath:v1/adduser.xsd" /> </bean> </property> <property name="portTypeName" value="AddUserPortType" /> <!-- 地址可使用Spring的PropertyPlaceholderConfigurer配置 --> <property name="locationUri" value="http://localhost:8080/dmsws/service" /> <property name="targetNamespace" value="http://www.dmsws.com/ws/schemas" /> </bean> </beans>
这里我的见解是:ws-servlet.xml中的配置是为了对外发布WSDL文档。
这里我们还剩下最后一步:编写服务端端点代码,SWS框架提供了很多对SOAP消息解析的接口,也就是说我们可以选择我们喜欢的方式解析SOAP消息内容。这里我使用XPath对消息进行解析。代码如下:
package com.org.dms.ws.service.ws; import javax.xml.parsers.DocumentBuilderFactory; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.Namespace; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.ResponsePayload; import org.springframework.ws.server.endpoint.annotation.XPathParam; import org.w3c.dom.Element; @Endpoint public class AddUserEndpoint { private static final String NAMESPACE_URI = "http://www.dmsws.com/ws/schemas"; @PayloadRoot(localPart = "AddUserRequest", namespace = NAMESPACE_URI) @Namespace(prefix = "ws", uri = NAMESPACE_URI) @ResponsePayload public Element addUser(@XPathParam("//ws:UserName") String userName, @XPathParam("//ws:UserAge") String userAge, @XPathParam("//ws:Pwd") String pwd) throws Exception { System.out.println("userName = " + userName); System.out.println("userAge = " + userAge); System.out.println("pwd = " + pwd); Element response = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument() .createElementNS(NAMESPACE_URI, "AddUserResponse"); response.setTextContent("1"); return response; } }
加载项目至tomcat7中,配置无误的话,启动应该是成功的。
在浏览器下输入我们的URL:http://localhost:8080/dmsws/AddUserService.wsdl,如果一切配置正确,此时你会看到我们对外发布的WSDL文件信息。
(请在外置浏览器下查看此链接地址,之前我在eclipse的内置浏览器下访问,页面没有任何显示。一片空白,调试了好久,查不到问题,还以为自己哪里配置错了,最后无意识的再外面浏览器下访问,WSDL文件就直接出来了)
如果我们这一步不编写服务端点的java类,只做到ws-servlet.xml配置的哪一步,wsdl文档是否可以生成呢?答案是可以。wsdl文档生成并不依赖我们编写的服务端代码,如AddUserEndpoint类。SWS框架通过我们配置声明的DefaultWsdl11Definition类及下面的参数(如XSD文件等)自动帮我们动态生成WSDL文件。
WSDL文件只是告诉客户端如何访问我们提供的WebService,而我们编写的Endpoint类是具体服务的实现。举个例子ws-servlet.xml就做菜的食材,而我们编写的Endpoint类是食材加工厂,可以对“传来”的食材进行加工,至于怎么加工,就是我们编写的方法内容了。所以二者缺一不可。
以上是服务端的编写内容。我在编写此Demo是遇到了不少问题,所以查了不少资料,主要参考了SWS官网的Doc文档,还有Spring3.X企业应用开发实战的附录内容,还有网上的一些其他Demo。但都有一些问题。希望这边文章可以帮助跟我一样遇到问题的人。
服务端生成了,现在还缺少客户端代码。下面使用JDK的wsimport命令生成客户端代码并进行测试。
JDK命令如下:
wsimport -d ./ -keep -verbose http://localhost:8080/dmsws/service/AddUserService.wsdl-d后面是代码生成后的保存路径,-verbose是显示生成过程的信息,-keep是为了生成.java文件。
参数正确的话,就可以在指定目录看到生成的java文件,我们将此文件Copy至任意EclipseJava工程下,为了简单,我直接将生成的文件(包含文件夹)copy至我们的SWS的demo项目,如下:
根据我们生成的工具类,我们就可以编写测试客户端代码了,代码如下:
package com.org.dms.ws.client;
import java.math.BigInteger;
import com.dmsws.ws.schemas.AddUserPortType;
import com.dmsws.ws.schemas.AddUserPortTypeService;
import com.dmsws.ws.schemas.AddUserRequest;
import com.dmsws.ws.schemas.UserType;
public class ActionLogClient {
public static void main(String[] args) {
UserType user = new UserType();
user.setPwd("password1234");
user.setUserAge("16");
user.setUserName("fuxiao");
AddUserRequest request = new AddUserRequest();
request.setUser(user);
AddUserPortTypeService service = new AddUserPortTypeService();
AddUserPortType pt = service.getAddUserPortTypeSoap11();
BigInteger n = pt.addUser(request);
System.out.println(n);
}
}
直接执行main方法,我们就可以在服务端控制台下,看到请求内容,如下:
至此demo编写完毕。希望可以帮助到大家,谢谢。
(本人才疏学浅,如有有不正确的地方希望大家海涵。)
相关文章推荐
- Maven搭建SpringWebService(2)-服务端service方法改写
- CXF3.0.1+spring+maven搭建webservice服务
- 使用Axis1.4 和 Spring2.5.6搭建最簡易的Webservice及如何在Windchill 7.0中配置(二)
- 利用Maven搭建Spring的开发环境
- intellij idea 12 搭建maven web项目 freemarker + spring mvc
- maven+springmvc+ibatis环境搭建
- Maven搭建webService (三) 创建客户端---使用Apache CXF方式实现
- Spring下搭建以Xfire实现的Webservice平台
- jersey+spring+maven 搭建实例helloworld
- killws 利用xfire部署webservice (xfire1.6+spring1.6+maven 进化版)
- killws 利用xfire部署webservice (xfire1.6+spring1.6+maven 初始版)
- 【Spring_WebService(CXF)】环境的搭建以及服务的暴露
- 利用Maven搭建Spring开发环境
- 利用Maven搭建Spring开发环境
- CXF搭建webService服务器(maven or jar)
- ibatis+spring+cxf+mysql搭建webservice
- xfire1.2.6+spring2.0 之webservice搭建小结
- Maven SpringMVC项目基本搭建(备忘)
- maven 下搭建spring
- maven+springMVC+mybatis+junit详细搭建过程