您的位置:首页 > 编程语言 > Java开发

Spring-ws提供SOAP服务的注意事项

2015-11-29 00:18 369 查看

本文在官方例子的基础上,使用JAXB marshall 和 unmarshall 处理 xml数据

依照官方的例子,我们需要处理一个假期的请求,以下是Holiday的xml格式:

<Holiday xmlns="http://mycompany.com/hr/schemas">
<StartDate>2006-07-03</StartDate>
<EndDate>2006-07-07</EndDate>
</Holiday>


以下是Employee的xml格式:

<Employee xmlns="http://mycompany.com/hr/schemas">
<Number>42</Number>
<FirstName>Arjen</FirstName>
<LastName>Poutsma</LastName>
</Employee>


那么一个请求就是下面的xml格式:

<HolidayRequest xmlns="http://mycompany.com/hr/schemas">
<Holiday>
<StartDate>2006-07-03</StartDate>
<EndDate>2006-07-07</EndDate>
</Holiday>
<Employee>
<Number>42</Number>
<FirstName>Arjen</FirstName>
<LastName>Poutsma</LastName>
</Employee>
</HolidayRequest>


我们需要为这个请求定义一个schema文件hr.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hr="http://mycompany.com/hr/schemas"
elementFormDefault="qualified"
targetNamespace="http://mycompany.com/hr/schemas">
<xs:element name="HolidayRequest">
<xs:complexType>
<xs:all>
<xs:element name="Holiday" type="hr:HolidayType"/>
<xs:element name="Employee" type="hr:EmployeeType"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="HolidayType">
<xs:sequence>
<xs:element name="StartDate" type="xs:date"/>
<xs:element name="EndDate" type="xs:date"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="EmployeeType">
<xs:sequence>
<xs:element name="Number" type="xs:integer"/>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>


在web.xml文件中添加处理soap的servlet:

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml
4000
/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>MyCompany HR Holiday Service</display-name>

<!-- take especial notice of the name of this servlet -->
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-ws.xml</param-value>
</init-param>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>


像SpringMVC有一个配置文件一样,spring-ws.xml是spring-ws的配置文件。这里解释一下MessageDispatcherServlet,Spring-ws的服务端是围绕着这个servlet设计的,这个servlet将收到的xml报文转发到endpoint,这一点跟SpringMVC的DispacherServlet很相似。MessageDispatcherServlet处理请求的转发过程如下图所示。



spring-ws.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" xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
<context:component-scan base-package="com.chinamobile.cmss.eshub.ssb.wssimulator" />

<sws:annotation-driven />

<sws:dynamic-wsdl id="holiday" portTypeName="HumanResource" locationUri="/ws/holidayService/" targetNamespace="http://mycompany.com/hr/definitions">
<sws:xsd location="classpath:schema/hr.xsd" />
</sws:dynamic-wsdl>
</beans>


我们开启自动扫描@Endpoint注解的类。接着定义暴露接口的wsdl路径。

下面开始写Endpoint。

package com.chinamobile.cmss.eshub.ssb.wssimulator.endpoint;

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 com.chinamobile.cmss.eshub.ssb.wssimulator.entity.HolidayRequest;

@Endpoint
public class HolidayEndpoint {

private static final String NAMESPACE_URI = "http://mycompany.com/hr/schemas";

@PayloadRoot(namespace = NAMESPACE_URI, localPart = "HolidayRequest")
public void handleHolidayRequest(@RequestPayload HolidayRequest holidayRequest)
throws Exception {
System.out.println(holidayRequest.toString());
}

}


这里使用了eclipselink的JAXB,项目的pom.xml需要特殊加入的配置如下。

<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>

<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>

<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>


编写Holiday.java实体类如下,注意与xml
date
对应的java类型不是
Date
,而是
XMLGregorianCalendar
,xml与java数据类型的对应关系参考这里

package com.chinamobile.cmss.eshub.ssb.wssimulator.entity;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.datatype.XMLGregorianCalendar;

@XmlAccessorType(XmlAccessType.FIELD)
public class Holiday {

@XmlElement(namespace="http://mycompany.com/hr/schemas")
private XMLGregorianCalendar StartDate;
@XmlElement(namespace="http://mycompany.com/hr/schemas")
private XMLGregorianCalendar EndDate;

public XMLGregorianCalendar getStartDate() {
return StartDate;
}
public void setStartDate(XMLGregorianCalendar startDate) {
StartDate = startDate;
}
public XMLGregorianCalendar getEndDate() {
return EndDate;
}
public void setEndDate(XMLGregorianCalendar endDate) {
EndDate = endDate;
}
@Override
public String toString() {
return "Holiday [StartDate=" + StartDate + ", EndDate=" + EndDate + "]";
}

}


编写Employee.java如下。

package com.chinamobile.cmss.eshub.ssb.wssimulator.entity;

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

@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

@XmlElement(namespace="http://mycompany.com/hr/schemas")
private int Number;
@XmlElement(namespace="http://mycompany.com/hr/schemas")
private String FirstName;
@XmlElement(namespace="http://mycompany.com/hr/schemas")
private String LastName;

public int getNumber() {
return Number;
}
public void setNumber(int number) {
Number = number;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
@Override
public String toString() {
return "Employee [Number=" + Number + ", FirstName=" + FirstName + ", LastName=" + LastName + "]";
}

}


在Spring-ws中使用JAXB的时候要注意,每个类要注明namespace,否则会报
A descriptor with default root element
的错误。类中的每个属性也要加
@XmlElement(namespace="")
的标记,否则在接收的时候为空,namespace与你制定的相同。

HolidayRequest.java代码如下。

package com.chinamobile.cmss.eshub.ssb.wssimulator.entity;

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

@XmlRootElement(name = "HolidayRequest", namespace="http://mycompany.com/hr/schemas")
@XmlAccessorType(XmlAccessType.FIELD)
public class HolidayRequest {
@XmlElement(namespace="http://mycompany.com/hr/schemas")
private Holiday Holiday;
@XmlElement(namespace="http://mycompany.com/hr/schemas")
private Employee Employee;

public Holiday getHoliday() {
return Holiday;
}
public void setHoliday(Holiday holiday) {
Holiday = holiday;
}
public Employee getEmployee() {
return Employee;
}
public void setEmployee(Employee employee) {
Employee = employee;
}
@Override
public String toString() {
return "HolidayRequest [Holiday=" + Holiday + ", Employee=" + Employee + "]";
}

}


在实体类相同的包下面创建
jaxb.properties
文件,内容为
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
,表示我们不使用默认的JAXB,而是使用eclipselink提供的实现,使用默认的JAXB要写更多的代码配置ObjectFactory,否则会报
doesnt contain ObjectFactory.class or jaxb.index
的错误。

到此我们在官方实例的基础上完成了一个更好用的样例。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  xml soap spring-ws jaxb