天天看點

spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。

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檔案了,如下:

spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。
spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。

2.4 根據wsdl檔案生成我們需要的java檔案

使用java自帶的wsimport指令生成檔案,如下:

cmd wsimport -d d:/webservice -keep http://localhost:8080/spring-webservice-server/service/UserService.wsdl
           

将所有的java檔案複制到我們的項目裡面來,如下:

spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。

對于上面生成的檔案要做以下幾點處理: 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([email protected])
 *
 * @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([email protected])
 *
 * @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方法,如下:

spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。

c. 測試我們的getUser方法, 如下:

spring webservice (一) 伺服器端開發1. 建立一個maven的web項目,完成一些準備工作。2. 開發webservice核心部分。

本教程的第一部分算是結束了, 源碼我也分享出來了:http://download.csdn.net/detail/kwgjbj/7283739, 下載下傳的時候需要1積分,算是給點辛苦費吧,比較寫這個教程還是很累的。

第二部分教程會寫一個用戶端與spring整合在一起。

參考文章: http://www.cnblogs.com/hippo0918/p/3662587.html

http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

繼續閱讀