spring webservice (一) 服务器端开发
最近研究了一下spring webservice整合,由于第一次做这个,整合期间遇到了不少问题,在网上查找了好久也没找到完整实现的server和client的demo,有的问题折腾了我好几天,看到spring的官网里面有人提相同的问题,但是都没人给出解决方案,所以就只能慢慢摸索,经过艰辛的探索,终于实现了一个完整的demo,在这里我整理了一下分享给大家,希望能帮助大家解决这方面遇到的问题,由于在下才疏学浅,有的地方可能写得不是很合理,希望大家提出来探讨一下,互相提高。我会尽量把自己遇到的问题体现出来,然后一一解决,废话不多说,开始干活:
第一部分实现spring webservice服务端的开发与部署。
1. 创建一个maven的web项目,完成一些准备工作。
1.1 在pom.xml中加入相关jar包,如下:
<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.zdsoft.webservice</groupId>
<artifactId>spring-webservice-server</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-webservice-server Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<finalName>spring-webservice-server</finalName>
</build>
</project>
1.2 创建log4j.xml文件,配置log4j打印信息,如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<param name="Threshold" value="ALL" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss:SSS} %p %l>> %m%n" />
</layout>
</appender>
<root>
<priority value="ALL" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
1.3 为了能让我们的webservice能和web的容器集成到一起,需要在web.xml里面做一些配置,如下:
<!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>
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<!--Spring-WS配置文件的位置,默认寻找[servlet-name]-servlet.xml文件 -->
<!--<init-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/spring-ws-config.xml</param-value>
</init-param> -->
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>*.wsdl</url-pattern>
</servlet-mapping>
</web-app>
解释上面的配置:
transformWsdlLocations
设置成true,就是说当你改变了项目名称或者端口号,你的服务还是可以正常访问的(但是如果你改变了WSDL的访问路径,发布服务的代码也要随之更改的)。
2. 开发webservice核心部分。
2.1 遵循契约优先的方式,我们先完成wsdl文件的编写,文件名:UserService.wsdl,放在WEB-INF/wsdl/下面,内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions targetNamespace="http://webservice.zdsoft.com/namespace/userservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webservice.zdsoft.com/namespace/userservice" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="UserService"> <wsdl:types> <xsd:schema targetNamespace="http://webservice.zdsoft.com/namespace/userservice"> <!-- xsd part start --> <xsd:element name="login" type="tns:login" /> <xsd:element name="loginResponse" type="tns:loginResponse" /> <xsd:element name="getUser" type="tns:getUser" /> <xsd:element name="getUserResponse" type="tns:getUserResponse" /> <xsd:complexType name="login"> <xsd:sequence> <xsd:element name="username" type="xsd:string" /> <xsd:element name="password" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="loginResponse"> <xsd:sequence> <xsd:element name="info" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getUser"> <xsd:sequence> <xsd:element name="username" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getUserResponse"> <xsd:sequence> <xsd:element name="user" type="tns:user" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="user"> <xsd:sequence> <xsd:element name="username" type="xsd:string" /> <xsd:element name="password" type="xsd:string" /> <xsd:element name="nickname" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <!-- xsd part end --> </xsd:schema> </wsdl:types> <wsdl:message name="login"> <wsdl:part element="tns:login" name="parameters" /> </wsdl:message> <wsdl:message name="loginResponse"> <wsdl:part element="tns:loginResponse" name="parameters" /> </wsdl:message> <wsdl:message name="getUser"> <wsdl:part element="tns:getUser" name="parameters" /> </wsdl:message> <wsdl:message name="getUserResponse"> <wsdl:part element="tns:getUserResponse" name="parameters" /> </wsdl:message> <wsdl:portType name="IUserService"> <wsdl:operation name="login"> <wsdl:input message="tns:login" /> <wsdl:output message="tns:loginResponse" /> </wsdl:operation> <wsdl:operation name="getUser"> <wsdl:input message="tns:getUser" /> <wsdl:output message="tns:getUserResponse" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="userServiceSOAP" type="tns:IUserService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="login"> <wsdl:input><soap:body use="literal" /></wsdl:input> <wsdl:output><soap:body use="literal" /></wsdl:output> </wsdl:operation> <wsdl:operation name="getUser"> <wsdl:input><soap:body use="literal" /></wsdl:input> <wsdl:output><soap:body use="literal" /></wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="UserService"> <wsdl:port binding="tns:userServiceSOAP" name="userServicePort"> <soap:address location="http://localhost:8080/spring-webservice-server/service/UserService.wsdl" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
PS: 上面xsd part这一段是可以单独写到一个UserService.xsd文件中去的,然后在include到这个wsdl里面来的,这样看着更正规、更清新一些,我没这样写的主要原因是待会用soapUI调试的时候会出现这个xsdl文件import错误,我也不知道是什么原因,不纠结这些工具的问题了,在spring里面可以通过这个xsd文件动态的创建wsdl文件,这样可以省下一些工作了,但我还是希望初学者自己动手写wsdl文件
。
2.2 编写spring的配置文件[spring-ws-servlet.xml],该文件放到WEB-INF/下面,内容如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:ws="http://www.springframework.org/schema/integration/ws"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
">
<context:component-scan base-package="com.zdsoft.webservice"/>
<sws:static-wsdl location="/WEB-INF/wsdl/UserService.wsdl"/>
<!-- 下面的配置可以动态的生成wsdl文件,我们只需要写一个简单的xsd文件就可以了 -->
<!--
<sws:dynamic-wsdl id="UserService" portTypeName="IUserService" targetNamespace="http://webservice.zdsoft.com/namespace/userservice"
locationUri="/service" serviceName="UserService" >
<sws:xsd location="/WEB-INF/wsdl/UserService.xsd" />
</sws:dynamic-wsdl>
-->
</beans>
2.3 启动我们的tomcat,在浏览器里面输入:http://localhost:8080/spring-webservice-server/service/UserService.wsdl,就可以看到我们wsdl文件了,如下:
2.4 根据wsdl文件生成我们需要的java文件
使用java自带的wsimport命令生成文件,如下:
cmd wsimport -d d:/webservice -keep http://localhost:8080/spring-webservice-server/service/UserService.wsdl
将所有的java文件复制到我们的项目里面来,如下:
对于上面生成的文件要做以下几点处理:
a. 将IUserService.java文件中带className的属性去掉:
@RequestWrapper(
localName = "login",
targetNamespace = "http://webservice.zdsoft.com/namespace/userservice",
className = "com.zdsoft.webservice.namespace.userservice.Login")
将上面的改成如下:
@RequestWrapper(
localName = "login",
targetNamespace = "http://webservice.zdsoft.com/namespace/userservice")
b.在GetUser.java, GetUserResponse.java,Login.java,LoginResponse.java中加上@XmlRootElement,并且指定名称空间,如下:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "login", propOrder = {
"username",
"password"
})
@XmlRootElement(name="login", namespace="http://webservice.zdsoft.com/namespace/userservice")
public class Login {
2.5 创建UserServiceImpl类,实现IUserService接口,如下:
package com.zdsoft.webservice.service;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.zdsoft.webservice.api.user.IUserService;
import com.zdsoft.webservice.api.user.User;
/**
* @author YuYang(zdsoft.yang@foxmail.com)
*
* @date 2014年5月2日
*/
@Component("userService")
public class UserServiceImpl implements IUserService {
private static final Logger LOG = LogManager.getLogger(UserServiceImpl.class);
public String login(String username, String password) {
LOG.info("Entered into UserServiceImpl method.");
LOG.debug("username:" + username);
LOG.debug("password:" + password);
String info = "login failed.";
if("scott".equals(username) && "tiger".equals(password)) {
info = "login success.";
}
LOG.debug(info);
LOG.info("Exit from UserServiceImpl method.");
return info;
}
public User getUser(String username) {
LOG.info("Entered into getUser method.");
LOG.debug(username);
User user = new User();
user.setNickname(username + "--nickname");
user.setPassword(username + "--password");
user.setUsername(username + "--username");
LOG.info("Exit from getUser method.");
return user;
}
}
2.6 创建endpoint类:UserServiceEndpoint,如下:
package com.zdsoft.webservice.endpoint;
import javax.annotation.Resource;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import com.zdsoft.webservice.api.user.GetUser;
import com.zdsoft.webservice.api.user.GetUserResponse;
import com.zdsoft.webservice.api.user.IUserService;
import com.zdsoft.webservice.api.user.Login;
import com.zdsoft.webservice.api.user.LoginResponse;
import com.zdsoft.webservice.api.user.User;
/**
* @author YuYang(zdsoft.yang@foxmail.com)
*
* @date 2014年5月2日
*/
@Endpoint
public class UserServiceEndpoint {
private static final Logger LOG = LogManager.getLogger(UserServiceEndpoint.class);
//UserService.wsdl声明的命名空间
public static final String USERVICE_NAMESPACE = "http://webservice.zdsoft.com/namespace/userservice";
@Resource(name="userService")
private IUserService userService;
@PayloadRoot(namespace = USERVICE_NAMESPACE, localPart = "login")
@ResponsePayload
public LoginResponse handelLoginRequest(@RequestPayload Login request) {
LOG.info("Entered into handelLoginRequest method.");
String info = userService.login(request.getUsername(), request.getPassword());
LoginResponse response = new LoginResponse();
response.setInfo(info);
LOG.info("Exit from handelLoginRequest method.");
return response;
}
@PayloadRoot(namespace = USERVICE_NAMESPACE, localPart = "getUser")
@ResponsePayload
public GetUserResponse HandelGetUserRequest(@RequestPayload GetUser request) {
LOG.info("Entered into HandelGetUserRequest method.");
User user = userService.getUser(request.getUsername());
GetUserResponse response = new GetUserResponse();
response.setUser(user);
LOG.info("Exit from HandelGetUserRequest method.");
return response;
}
}
2.7 使用SoapUI工具测试
a. 下载SoapUI,官网:
http://www.soapui.org/, 这个工具使用方法去Google一下。
b. 测试我们的login方法,如下:
c. 测试我们的getUser方法, 如下:
本教程的第一部分算是结束了, 源码我也分享出来了:
http://download.csdn.net/detail/kwgjbj/7283739
, 下载的时候需要1积分,算是给点辛苦费吧,比较写这个教程还是很累的。
第二部分教程会写一个客户端与spring整合在一起。
参考文章:
版权声明:本文为kwgjbj原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。