SpringWS(二)-入门

    官方帮助手册:http://docs.spring.io/spring-ws/site/reference/html/tutorial.html

    接着《SpringWS(一)-环境搭建》所搭建的服务,运行项目访问地址:http://localhost:8080/Spring-WS-Demo-01/service/UserService.wsdl;SpringWS会根据我们定义的Schema来生成wsdl。那这篇文章就继续开展我们的后台处理逻辑,究竟SpringWS对于Web Service请求是如何处理的?过于细节的东西就不详细说了,后续的博客都会提到,现在先把大概的脉络搭建起来。

一、根据SpringWS生成的WSDL,服务端根据接口来定义AddRequest.java,AddResponse.java等文件,但是这些工作是可以交给MyEclipse去生成的,可以通过NEW->“Web Service Client”,不清楚的可以百度。虽然MyEclipse会自动帮我们生成很多文件,但是用到的就那几个,分别是AddRequest,AddResponse,GetUserByUserNameRequest,GetUserByUserNameResponse,User 如下:

package ws.user.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import ws.user.endpoint.UserServiceEndpoint;

/**
 * <p>
 * Java class for anonymous complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;all>
 *         &lt;element ref="{http://localhost/ws/UserService}User"/>
 *       &lt;/all>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "AddRequest", namespace=UserServiceEndpoint.USER_SERVICE_NAMESPACE)
public class AddRequest {

    @XmlElement(name = "User", namespace = "http://localhost/ws/UserService", required = true)
    protected User user;

    /**
     * Gets the value of the user property.
     * 
     * @return possible object is {@link User }
     * 
     */
    public User getUser() {
        return user;
    }

    /**
     * Sets the value of the user property.
     * 
     * @param value
     *            allowed object is {@link User }
     * 
     */
    public void setUser(User value) {
        this.user = value;
    }

}
View Code
package ws.user.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import ws.user.endpoint.UserServiceEndpoint;

/**
 * <p>
 * Java class for anonymous complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;all>
 *         &lt;element name="success" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
 *       &lt;/all>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "AddResponse", namespace=UserServiceEndpoint.USER_SERVICE_NAMESPACE)
public class AddResponse {

    protected boolean success;

    /**
     * Gets the value of the success property.
     * 
     */
    public boolean isSuccess() {
        return success;
    }

    /**
     * Sets the value of the success property.
     * 
     */
    public void setSuccess(boolean value) {
        this.success = value;
    }

}
View Code
package ws.user.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import ws.user.endpoint.UserServiceEndpoint;

/**
 * <p>
 * Java class for anonymous complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;all>
 *         &lt;element name="username">
 *           &lt;simpleType>
 *             &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
 *               &lt;maxLength value="20"/>
 *             &lt;/restriction>
 *           &lt;/simpleType>
 *         &lt;/element>
 *       &lt;/all>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "GetUserByUserNameRequest", namespace=UserServiceEndpoint.USER_SERVICE_NAMESPACE)
public class GetUserByUserNameRequest {

    @XmlElement(required = true)
    protected String username;

    /**
     * Gets the value of the username property.
     * 
     * @return possible object is {@link String }
     * 
     */
    public String getUsername() {
        return username;
    }

    /**
     * Sets the value of the username property.
     * 
     * @param value
     *            allowed object is {@link String }
     * 
     */
    public void setUsername(String value) {
        this.username = value;
    }

}
View Code
package ws.user.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import ws.user.endpoint.UserServiceEndpoint;

/**
 * <p>
 * Java class for anonymous complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;all>
 *         &lt;element ref="{http://localhost/ws/UserService}User"/>
 *       &lt;/all>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "GetUserByUserNameResponse", namespace=UserServiceEndpoint.USER_SERVICE_NAMESPACE)
public class GetUserByUserNameResponse {

    @XmlElement(name = "User", namespace = "http://localhost/ws/UserService", required = true)
    protected User user;

    /**
     * Gets the value of the user property.
     * 
     * @return possible object is {@link User }
     * 
     */
    public User getUser() {
        return user;
    }

    /**
     * Sets the value of the user property.
     * 
     * @param value
     *            allowed object is {@link User }
     * 
     */
    public void setUser(User value) {
        this.user = value;
    }

}
View Code
package ws.user.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import ws.user.endpoint.UserServiceEndpoint;

/**
 * <p>
 * Java class for anonymous complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;all>
 *         &lt;element name="username">
 *           &lt;simpleType>
 *             &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
 *               &lt;pattern value="[a-zA-Z0-9]{1,20}"/>
 *             &lt;/restriction>
 *           &lt;/simpleType>
 *         &lt;/element>
 *         &lt;element name="password">
 *           &lt;simpleType>
 *             &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
 *               &lt;minLength value="6"/>
 *               &lt;maxLength value="15"/>
 *             &lt;/restriction>
 *           &lt;/simpleType>
 *         &lt;/element>
 *       &lt;/all>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "User", namespace=UserServiceEndpoint.USER_SERVICE_NAMESPACE)
public class User {

    @XmlElement(required = true)
    protected String username;
    @XmlElement(required = true)
    protected String password;

    /**
     * Gets the value of the username property.
     * 
     * @return possible object is {@link String }
     * 
     */
    public String getUsername() {
        return username;
    }

    /**
     * Sets the value of the username property.
     * 
     * @param value
     *            allowed object is {@link String }
     * 
     */
    public void setUsername(String value) {
        this.username = value;
    }

    /**
     * Gets the value of the password property.
     * 
     * @return possible object is {@link String }
     * 
     */
    public String getPassword() {
        return password;
    }

    /**
     * Sets the value of the password property.
     * 
     * @param value
     *            allowed object is {@link String }
     * 
     */
    public void setPassword(String value) {
        this.password = value;
    }

}
View Code

 PS:自动生成的几个类,可能还有点美中不足的地方,就是在每个类@XmlRootElement中没有指定命名空间,所以当我们用MyEclipse生成的时候,最后记得把命名空间补上,这里可以方便SpringWS帮我们完成XML的序列化工作,我们只管写业务逻辑就足够了(上面的类中我已经补充完整了)。

二、我现在发布了服务,客户端可以向服务端发送请求,那服务端怎么接收请求并回应呢?新建一个类,代码如下(这里列举了几个endpoind的处理方式,可以选择自己需要的处理方式):

package ws.user.endpoint;

import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ws.context.MessageContext;
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 ws.user.model.AddRequest;
import ws.user.model.AddResponse;
import ws.user.service.IUserServcie;

@Endpoint
public class UserServiceEndpoint {

    //UserService.xsd声明的命名空间
    public static final String USER_SERVICE_NAMESPACE = "http://localhost/ws/UserService";

    //注入业务逻辑处理对象
    @Value("#{userServcie}")
    private IUserServcie userServcie;
    
    @PayloadRoot(namespace = USER_SERVICE_NAMESPACE, localPart = "AddRequest")
    public @ResponsePayload AddResponse handleAddRequest(@RequestPayload AddRequest addRequest)
            throws Exception {
        //业务逻辑处理
        boolean success = userServcie.add(addRequest.getUser());
        AddResponse response = new AddResponse();
        response.setSuccess(success);
        return response;
    }
    
    /*@PayloadRoot(namespace = USER_SERVICE_NAMESPACE, localPart = "AddRequest")
    public @ResponsePayload AddResponse handleAddRequest(@RequestPayload DOMSource domSource, SoapHeader header) throws TransformerException {
        StringResult rs = new StringResult();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.transform(domSource, rs);
        System.out.println(rs);
        System.out.println(header.getAllAttributes().hasNext());
        while(header.getAllAttributes().hasNext()) {
            System.out.println(header.getAllAttributes().next());
        }
        AddResponse response = new AddResponse();
        response.setSuccess(false);
        return response;
    }*/
    
    /*@PayloadRoot(namespace = USER_SERVICE_NAMESPACE, localPart = "AddRequest")
    public @ResponsePayload AddResponse handle(@RequestPayload Element element) {
        //element:原始的XML报文
        System.out.println(element.asXML());
        AddResponse response = new AddResponse();
        response.setSuccess(false);
        return response;
    }*/
    
    /*
    @PayloadRoot(namespace = USER_SERVICE_NAMESPACE, localPart = "AddRequest")
    public @ResponsePayload AddResponse handle(@RequestPayload AddRequest addRequest, @RequestPayload Element element, MessageContext messageContext) {
        //element:原始的XML报文
        System.out.println(addRequest == null);
        System.out.println(addRequest.getUser().getUsername());
        System.out.println(element.asXML());
        AddResponse response = new AddResponse();
        response.setSuccess(false);
        return response;
    }
    */
}

 

 客户端(soupui)发送请求报文(soupui的使用可以在网上找到):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:user="http://localhost/ws/UserService">
   <soapenv:Header/>
   <soapenv:Body>
      <user:AddRequest>
         <user:User>
            <!--You may enter the following 2 items in any order-->
            <username>123</username>
            <password>123123123</password>
         </user:User>
      </user:AddRequest>
   </soapenv:Body>
</soapenv:Envelope>

下面是客户端接收到的报文:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns3:AddResponse xmlns:ns3="http://localhost/ws/UserService">
         <success>true</success>
      </ns3:AddResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

先对上面注解代码和请求报文和回应报文解释一下:

  1. @Endpoint:是指消息的接收者,就是SpringWS的endpoint,可以一个或者多个,关键是下面的注解。
  2. @PayloadRoot:是指soap消息中的需要被调用的方法,它包括两个参数:localPart的值实质上就是请求报文中的一个节点(AddRequest),而namespace就是指我定义在Schema的命名空间。
  3. @RequestPayload:是指请求的实例。当客户端发送消息过来,服务端接收到的实际是XML报文,在调用此方法之前,SpringWS已经帮我们把XML序列化成实例了(我们在之前已经生成对应的AddRequest和AddResponse等class,并指明命名空间)。
  4. @ResponsePayload:是指最终返回的实例,而客户端最终也是以XML返回给客户端。

 三、剩下的工作就是让spring扫描注解,对spring-ws-servlet.xml进行修改:

<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:int="http://www.springframework.org/schema/integration" 
    xmlns:ws="http://www.springframework.org/schema/integration/ws"
    xmlns:util="http://www.springframework.org/schema/util" 
    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/integration/ws
    http://www.springframework.org/schema/integration/ws/spring-integration-ws-2.2.xsd
    http://www.springframework.org/schema/web-services
    http://www.springframework.org/schema/web-services/web-services-2.0.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-3.1.xsd
    http://www.springframework.org/schema/integration
    http://www.springframework.org/schema/integration/spring-integration-2.2.xsd">
    <!-- begin:(二)-入门 -->
    <context:component-scan base-package="ws.user.endpoint"/>
    <context:component-scan base-package="ws.user.model"/>
    <bean id="userServcie" class="ws.user.service.IUserServcieImpl"/>
    <!-- end:(二)-入门 -->
    <!-- begin:(一)-环境搭建 -->
    <sws:dynamic-wsdl id="UserService" portTypeName="UserServicePortType" targetNamespace="http://localhost/ws/UserService"
        locationUri="/service/user" serviceName="UserService">
        <sws:xsd location="/WEB-INF/xsd/UserService.xsd"/>
    </sws:dynamic-wsdl>
    <!-- end:(一)-环境搭建 -->
</beans>

 以上的内容就到这里,源码的下载地址没变,有什么问题欢迎通过邮件交流,谢谢。

posted @ 2014-04-19 23:04  lizebin0918  Views(939)  Comments(0Edit  收藏  举报