提交 a1f0f68b 编写于 作者: 茶陵後's avatar 茶陵後 👍

#24 spring web service

上级 947ab7df
# Spring Web Services Reference Documentation
## [](#overview)Preface
## Preface
In the current age of Service Oriented Architectures, more and more people use web services to connect previously unconnected systems. Initially, web services were considered to be just another way to do a Remote Procedure Call (RPC). Over time, however, people found out that there is a big difference between RPCs and web services. Especially when interoperability with other platforms is important, it is often better to send encapsulated XML documents that contain all the data necessary to process the request. Conceptually, XML-based web services are better compared to message queues than to remoting solutions. Overall, XML should be considered the platform-neutral representation of data, the *common language* of SOA. When developing or using web services, the focus should be on this XML and not on Java.
Spring Web Services focuses on creating these document-driven web services. Spring Web Services facilitates contract-first SOAP service development, allowing for the creation of flexible web services by using one of the many ways to manipulate XML payloads. Spring-WS provides a powerful [message dispatching framework](#server), a [WS-Security](#security) solution that integrates with your existing application security solution, and a [Client-side API](#client) that follows the familiar Spring template pattern.
# [](#_i_introduction)I. Introduction
# I. Introduction
This first part of the reference documentation [is an overview](#what-is-spring-ws) of Spring Web Services and the underlying concepts. Spring-WS is then introduced, and [the concepts](#why-contract-first) behind contract-first web service development are explained.
## [](#what-is-spring-ws)1. What is Spring Web Services?
## 1. What is Spring Web Services?
### [](#_introduction)1.1. Introduction
### 1.1. Introduction
Spring Web Services (Spring-WS) is a product of the Spring community and is focused on creating document-driven web services. Spring Web Services aims to facilitate contract-first SOAP service development, allowing for the creation of flexible web services by using one of the many ways to manipulate XML payloads. The product is based on Spring itself, which means you can use the Spring concepts (such as dependency injection) as an integral part of your web service.
......@@ -32,35 +32,35 @@ People use Spring-WS for many reasons, but most are drawn to it after finding al
* [Apache license](#features-apache-license)
#### [](#features-powerful-mappings)1.1.1. Powerful mappings
#### 1.1.1. Powerful mappings
You can distribute incoming XML requests to any object, depending on message payload, SOAP Action header, or an XPath expression.
#### [](#features-xml-api-support)1.1.2. XML API support
#### 1.1.2. XML API support
Incoming XML messages can be handled not only with standard JAXP APIs such as DOM, SAX, and StAX, but also with JDOM, dom4j, XOM, or even marshalling technologies.
#### [](#features-flexible-xml-marshalling)1.1.3. Flexible XML Marshalling
#### 1.1.3. Flexible XML Marshalling
Spring Web Services builds on the Object/XML Mapping module in the Spring Framework, which supports JAXB 1 and 2, Castor, XMLBeans, JiBX, and XStream.
#### [](#features-reusing-your-spring-expertise)1.1.4. Reusing Your Spring expertise
#### 1.1.4. Reusing Your Spring expertise
Spring-WS uses Spring application contexts for all configuration, which should help Spring developers get up-to-speed quickly. Also, the architecture of Spring-WS resembles that of Spring-MVC.
#### [](#features-support-for-ws-security)1.1.5. Support for WS-Security
#### 1.1.5. Support for WS-Security
WS-Security lets you sign SOAP messages, encrypt and decrypt them, or authenticate against them.
#### [](#features-integration-with-spring-security)1.1.6. Integration with Spring Security
#### 1.1.6. Integration with Spring Security
The WS-Security implementation of Spring Web Services provides integration with Spring Security. This means you can use your existing Spring Security configuration for your SOAP service as well.
#### [](#features-apache-license)1.1.7. Apache license
#### 1.1.7. Apache license
You can confidently use Spring-WS in your project.
### [](#_runtime_environment)1.2. Runtime environment
### 1.2. Runtime environment
Spring Web Services requires a standard Java 8 Runtime Environment. Spring-WS is built on Spring Framework 4.0.9, but higher versions are supported.
......@@ -78,7 +78,7 @@ The following figure shows and the dependencies between the Spring-WS modules. A
![spring deps](spring-deps.png)
### [](#_supported_standards)1.3. Supported standards
### 1.3. Supported standards
Spring Web Services supports the following standards:
......@@ -92,7 +92,7 @@ Spring Web Services supports the following standards:
* SOAP Message Security 1.1, Username Token Profile 1.1, X.509 Certificate Token Profile 1.1, SAML Token Profile 1.1, Kerberos Token Profile 1.1, Basic Security Profile 1.1
## [](#why-contract-first)2. Why Contract First?
## 2. Why Contract First?
When creating web services, there are two development styles: contract-last and contract-first. When you use a contract-last approach, you start with the Java code and let the web service contract (in WSDL — see sidebar) be generated from that. When using contract-first, you start with the WSDL contract and use Java to implement the contract.
......@@ -102,14 +102,14 @@ WSDL stands for Web Service Description Language. A WSDL file is an XML document
Spring-WS supports only the contract-first development style, and this section explains why.
### [](#_objectxml_impedance_mismatch)2.1. Object/XML Impedance Mismatch
### 2.1. Object/XML Impedance Mismatch
Similar to the field of ORM, where we have an [Object/Relational impedance mismatch](https://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch), converting Java objects to XML has a similar problem. At first glance, the O/X mapping problem appears simple: Create an XML element for each Java object to convert all Java properties and fields to sub-elements or attributes. However, things are not as simple as they appear, because there is a fundamental difference between hierarchical languages, such as XML (and especially XSD), and the graph model of Java.
| |Most of the contents in this section were inspired by [[alpine]](#alpine) and [[effective-enterprise-java]](#effective-enterprise-java).|
|---|----------------------------------------------------------------------------------------------------------------------------------------|
#### [](#_xsd_extensions)2.1.1. XSD Extensions
#### 2.1.1. XSD Extensions
In Java, the only way to change the behavior of a class is to subclass it to add the new behavior to that subclass. In XSD, you can extend a data type by restricting it — that is, constraining the valid values for the elements and attributes. For instance, consider the following example:
......@@ -123,7 +123,7 @@ In Java, the only way to change the behavior of a class is to subclass it to add
This type restricts a XSD string by way of a regular expression, allowing only three upper case letters. If this type is converted to Java, we end up with an ordinary `java.lang.String`. The regular expression is lost in the conversion process, because Java does not allow for these sorts of extensions.
#### [](#_unportable_types)2.1.2. Unportable Types
#### 2.1.2. Unportable Types
One of the most important goals of a web service is to be interoperable: to support multiple platforms such as Java, .NET, Python, and others. Because all of these languages have different class libraries, you must use some common, cross-language format to communicate between them. That format is XML, which is supported by all of these languages.
......@@ -157,7 +157,7 @@ This problem is also present when working on the client side. Consider the follo
This contract defines a request that takes an `date`, which is a XSD datatype representing a year, month, and day. If we call this service from Java, we probably use either a `java.util.Date` or `java.util.Calendar`. However, both of these classes actually describe times, rather than dates. So, we actually end up sending data that represents the fourth of April 2007 at midnight (`2007-04-04T00:00:00`), which is not the same as `2007-04-04`.
#### [](#_cyclic_graphs)2.1.3. Cyclic Graphs
#### 2.1.3. Cyclic Graphs
Imagine we have the following class structure:
......@@ -215,7 +215,7 @@ This solves the recursion problem but introduces new ones. For one, you cannot u
These are just a few of the problems when dealing with O/X mapping. It is important to respect these issues when writing web services. The best way to respect them is to focus on the XML completely, while using Java as an implementation language. This is what contract-first is all about.
### [](#_contract_first_versus_contract_last)2.2. Contract-first Versus Contract-last
### 2.2. Contract-first Versus Contract-last
Besides the Object/XML Mapping issues mentioned in the previous section, there are other reasons for preferring a contract-first development style.
......@@ -227,7 +227,7 @@ Besides the Object/XML Mapping issues mentioned in the previous section, there a
* [Versioning](#contract-first-versioning)
#### [](#contract-first-fragility)2.2.1. Fragility
#### 2.2.1. Fragility
As mentioned earlier, the contract-last development style results in your web service contract (WSDL and your XSD) being generated from your Java contract (usually an interface). If you use this approach, you have no guarantee that the contract stays constant over time. Each time you change your Java contract and redeploy it, there might be subsequent changes to the web service contract.
......@@ -237,13 +237,13 @@ When a web service contract changes, users of the contract have to be instructed
For a contract to be useful, it must remain constant for as long as possible. If a contract changes, you have to contact all the users of your service and instruct them to get the new version of the contract.
#### [](#contract-first-performance)2.2.2. Performance
#### 2.2.2. Performance
When a Java object is automatically transformed into XML, there is no way to be sure as to what is sent across the wire. An object might reference another object, which refers to another, and so on. In the end, half of the objects on the heap in your virtual machine might be converted into XML, which results in slow response times.
When using contract-first, you explicitly describe what XML is sent where, thus making sure that it is exactly what you want.
#### [](#contract-first-reusability)2.2.3. Reusability
#### 2.2.3. Reusability
Defining your schema in a separate file lets you reuse that file in different scenarios. Consider the definition of an `AirportCode` in a file called `airline.xsd`:
......@@ -257,13 +257,13 @@ Defining your schema in a separate file lets you reuse that file in different sc
You can reuse this definition in other schemas, or even WSDL files, by using an `import` statement.
#### [](#contract-first-versioning)2.2.4. Versioning
#### 2.2.4. Versioning
Even though a contract must remain constant for as long as possible, they do need to be changed sometimes. In Java, this typically results in a new Java interface, such as `AirlineService2`, and a (new) implementation of that interface. Of course, the old service must be kept around, because there might be clients who have not yet migrated.
If using contract-first, we can have a looser coupling between contract and implementation. Such a looser coupling lets us implement both versions of the contract in one class. We could, for instance, use an XSLT stylesheet to convert any “old-style” messages to the “new-style” messages.
## [](#tutorial)3. Writing Contract-First Web Services
## 3. Writing Contract-First Web Services
This tutorial shows you how to write [contract-first web services](#why-contract-first) — that is, how to develop web services that start with the XML Schema or WSDL contract first followed by the Java code second. Spring-WS focuses on this development style, and this tutorial should help you get started. Note that the first part of this tutorial contains almost no Spring-WS specific information. It is mostly about XML, XSD, and WSDL. The [second part](#tutorial-creating-project) focuses on implementing this contract with Spring-WS .
......@@ -271,11 +271,11 @@ The most important thing when doing contract-first web service development is to
In this tutorial, we define a web service that is created by a Human Resources department. Clients can send holiday request forms to this service to book a holiday.
### [](#_messages)3.1. Messages
### 3.1. Messages
In this section, we focus on the actual XML messages that are sent to and from the web service. We start out by determining what these messages look like.
#### [](#_holiday)3.1.1. Holiday
#### 3.1.1. Holiday
In the scenario, we have to deal with holiday requests, so it makes sense to determine what a holiday looks like in XML:
......@@ -288,7 +288,7 @@ In the scenario, we have to deal with holiday requests, so it makes sense to det
A holiday consists of a start date and an end date. We have also decided to use the standard [ISO 8601](https://www.cl.cam.ac.uk/~mgk25/iso-time.html) date format for the dates, because that saves a lot of parsing hassle. We have also added a namespace to the element, to make sure our elements can used within other XML documents.
#### [](#_employee)3.1.2. Employee
#### 3.1.2. Employee
There is also the notion of an employee in the scenario. Here is what it looks like in XML:
......@@ -302,7 +302,7 @@ There is also the notion of an employee in the scenario. Here is what it looks l
We have used the same namespace as before. If this `<Employee/>` element could be used in other scenarios, it might make sense to use a different namespace, such as `[http://example.com/employees/schemas](http://example.com/employees/schemas)`.
#### [](#_holidayrequest)3.1.3. HolidayRequest
#### 3.1.3. HolidayRequest
Both the `holiday` element and the `employee` element can be put in a `<HolidayRequest/>`:
......@@ -322,7 +322,7 @@ Both the `holiday` element and the `employee` element can be put in a `<HolidayR
The order of the two elements does not matter: `<Employee/>` could have been the first element. What matters is that all of the data is there. In fact, the data is the only thing that is important: We take a data-driven approach.
### [](#tutorial.xsd)3.2. Data Contract
### 3.2. Data Contract
Now that we have seen some examples of the XML data that we can use, it makes sense to formalize this into a schema. This data contract defines the message format we accept. There are four different ways of defining such a contract for XML:
......@@ -459,7 +459,7 @@ Clearly, we must make sure that the start and end date are really dates. XML Sch
We store this file as `hr.xsd`.
### [](#tutorial-service-contract)3.3. Service Contract
### 3.3. Service Contract
A service contract is generally expressed as a [WSDL](https://www.w3.org/TR/wsdl) file. Note that, in Spring-WS, writing the WSDL by hand is not required. Based on the XSD and some conventions, Spring-WS can create the WSDL for you, as explained in the section entitled [Implementing the Endpoint](#tutorial-implementing-endpoint). The remainder of this section shows how to write WSDL by hand. You may want to skip to [the next section](#tutorial-creating-project).
......@@ -551,7 +551,7 @@ Adding a concrete part is pretty standard. To do so, refer to the abstract part
The preceding listing shows the final WSDL. We describe how to implement the resulting schema and WSDL in the next section.
### [](#tutorial-creating-project)3.4. Creating the project
### 3.4. Creating the project
In this section, we use [Maven](https://maven.apache.org/) to create the initial project structure for us. Doing so is not required but greatly reduces the amount of code we have to write to setup our HolidayService.
......@@ -596,11 +596,11 @@ In addition to the preceding `WEB-INF/web.xml` file, you also need another, Spri
Once you had the project structure created, you can put the schema and the WSDL from the previous section into `'WEB-INF/'` folder.
### [](#tutorial-implementing-endpoint)3.5. Implementing the Endpoint
### 3.5. Implementing the Endpoint
In Spring-WS, you implement endpoints to handle incoming XML messages. An endpoint is typically created by annotating a class with the `@Endpoint` annotation. In this endpoint class, you can create one or more methods that handle incoming request. The method signatures can be quite flexible. You can include almost any sort of parameter type related to the incoming XML message, as we explain later in this chapter.
#### [](#_handling_the_xml_message)3.5.1. Handling the XML Message
#### 3.5.1. Handling the XML Message
In this sample application, we use [JDom 2](http://www.jdom.org/) to handle the XML message. We also use [XPath](https://www.w3.org/TR/xpath20/), because it lets us select particular parts of the XML JDOM tree without requiring strict schema conformance.
......@@ -724,7 +724,7 @@ Here is how we would configure these classes in our `spring-ws-servlet.xml` Spri
</beans>
```
#### [](#_routing_the_message_to_the_endpoint)3.5.2. Routing the Message to the Endpoint
#### 3.5.2. Routing the Message to the Endpoint
As part of writing the endpoint, we also used the `@PayloadRoot` annotation to indicate which sort of messages can be handled by the `handleHolidayRequest` method. In Spring-WS, this process is the responsibility of an `EndpointMapping`. Here, we route messages based on their content by using a `PayloadRootAnnotationMethodEndpointMapping`. The following listing shows the annotation we used earlier:
......@@ -736,7 +736,7 @@ The annotation shown in the preceding example basically means that whenever an X
There are also other ways to map endpoints to XML messages, which is described in [the next chapter](#common).
#### [](#_providing_the_service_and_stub_implementation)3.5.3. Providing the Service and Stub implementation
#### 3.5.3. Providing the Service and Stub implementation
Now that we have the endpoint, we need `HumanResourceService` and its implementation for use by `HolidayEndpoint`. The following listing shows the `HumanResourceService` interface:
......@@ -770,7 +770,7 @@ public class StubHumanResourceService implements HumanResourceService {
|**1**|The `StubHumanResourceService` is annotated with `@Service`. This marks the class as a business facade, which makes this a candidate for injection by `@Autowired` in `HolidayEndpoint`.|
|-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#tutorial-publishing-wsdl)3.6. Publishing the WSDL
### 3.6. Publishing the WSDL
Finally, we need to publish the WSDL. As stated in [Service Contract](#tutorial-service-contract), we do not need to write a WSDL ourselves. Spring-WS can generate one based on some conventions. Here is how we define the generation:
......@@ -803,19 +803,19 @@ You can create a WAR file by using `mvn install`. If you deploy the application
That concludes this tutorial. The tutorial code can be found in the full distribution of Spring-WS. If you wish to continue, look at the echo sample application that is part of the distribution. After that, look at the airline sample, which is a bit more complicated, because it uses JAXB, WS-Security, Hibernate, and a transactional service layer. Finally, you can read the rest of the reference documentation.
# [](#_ii_reference)II. Reference
# II. Reference
This part of the reference documentation details the various components that comprise Spring Web Services. This includes [a chapter](#common) that discusses the parts common to both client- and server-side WS, a chapter devoted to the specifics of [writing server-side web services](#server), a chapter about using web services on [the client-side](#client), and a chapter on using [WS-Security](#security).
## [](#common)4. Shared components
## 4. Shared components
This chapter explores the components that are shared between client- and server-side Spring-WS development. These interfaces and classes represent the building blocks of Spring-WS, so you need to understand what they do, even if you do not use them directly.
### [](#web-service-messages)4.1. Web Service Messages
### 4.1. Web Service Messages
This section describes the messages and message factories that Spring-WS uses.
#### [](#web-service-message)4.1.1. `WebServiceMessage`
#### 4.1.1. `WebServiceMessage`
One of the core interfaces of Spring Web Services is the `WebServiceMessage`. This interface represents a protocol-agnostic XML message. The interface contains methods that provide access to the payload of the message, in the form of a `javax.xml.transform.Source` or a `javax.xml.transform.Result`. `Source` and `Result` are tagging interfaces that represent an abstraction over XML input and output. Concrete implementations wrap various XML representations, as indicated in the following table:
......@@ -830,15 +830,15 @@ One of the core interfaces of Spring Web Services is the `WebServiceMessage`. Th
In addition to reading from and writing to the payload, a web service message can write itself to an output stream.
#### [](#soap-message)4.1.2. `SoapMessage`
#### 4.1.2. `SoapMessage`
`SoapMessage` is a subclass of `WebServiceMessage`. It contains SOAP-specific methods, such as getting SOAP Headers, SOAP Faults, and so on. Generally, your code should not be dependent on `SoapMessage`, because the content of the SOAP Body (the payload of the message) can be obtained by using `getPayloadSource()` and `getPayloadResult()` in the `WebServiceMessage`. Only when it is necessary to perform SOAP-specific actions (such as adding a header, getting an attachment, and so on) should you need to cast `WebServiceMessage` to `SoapMessage`.
#### [](#message-factories)4.1.3. Message Factories
#### 4.1.3. Message Factories
Concrete message implementations are created by a `WebServiceMessageFactory`. This factory can create an empty message or read a message from an input stream. There are two concrete implementations of `WebServiceMessageFactory`. One is based on SAAJ, the SOAP with Attachments API for Java. The other is based on Axis 2’s AXIOM (AXis Object Model).
##### [](#_saajsoapmessagefactory)`SaajSoapMessageFactory`
##### `SaajSoapMessageFactory`
The `SaajSoapMessageFactory` uses the SOAP with Attachments API for Java (SAAJ) to create `SoapMessage` implementations. SAAJ is part of J2EE 1.4, so it should be supported under most modern application servers. Here is an overview of the SAAJ versions supplied by common application servers:
......@@ -859,7 +859,7 @@ Additionally, Java SE 6 includes SAAJ 1.3. You can wire up a `SaajSoapMessageFac
| |SAAJ is based on DOM, the Document Object Model. This means that all SOAP messages are stored in memory. For larger SOAP messages, this may not be performant. In that case, the `AxiomSoapMessageFactory` might be more applicable.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
##### [](#_axiomsoapmessagefactory)`AxiomSoapMessageFactory`
##### `AxiomSoapMessageFactory`
The `AxiomSoapMessageFactory` uses the AXis 2 Object Model (AXIOM) to create `SoapMessage` implementations. AXIOM is based on StAX, the Streaming API for XML. StAX provides a pull-based mechanism for reading XML messages, which can be more efficient for larger messages.
......@@ -879,7 +879,7 @@ Full streaming for AXIOM is used when a handler method returns a JAXB2-supported
For more information about full streaming, see the class-level Javadoc for `StreamingWebServiceMessage` and `StreamingPayload`.
##### [](#soap_11_or_12)SOAP 1.1 or 1.2
##### SOAP 1.1 or 1.2
Both the `SaajSoapMessageFactory` and the `AxiomSoapMessageFactory` have a `soapVersion` property, where you can inject a `SoapVersion` constant. By default, the version is 1.1, but you can set it to 1.2:
......@@ -906,13 +906,13 @@ In the preceding example, we define a `SaajSoapMessageFactory` that accepts only
| |Even though both versions of SOAP are quite similar in format, the 1.2 version is not backwards compatible with 1.1, because it uses a different XML namespace. Other major differences between SOAP 1.1 and 1.2 include the different structure of a fault and the fact that `SOAPAction` HTTP headers are effectively deprecated, though they still work.<br/><br/>One important thing to note with SOAP version numbers (or WS-\* specification version numbers in general) is that the latest version of a specification is generally not the most popular version. For SOAP, this means that (currently) the best version to use is 1.1. Version 1.2 might become more popular in the future, but 1.1 is currently the safest bet.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#message-context)4.1.4. `MessageContext`
#### 4.1.4. `MessageContext`
Typically, messages come in pairs: a request and a response. A request is created on the client-side, which is sent over some transport to the server-side, where a response is generated. This response gets sent back to the client, where it is read.
In Spring Web Services, such a conversation is contained in a `MessageContext`, which has properties to get request and response messages. On the client-side, the message context is created by the [`WebServiceTemplate`](#client-web-service-template). On the server-side, the message context is read from the transport-specific input stream. For example, in HTTP, it is read from the `HttpServletRequest`, and the response is written back to the `HttpServletResponse`.
### [](#transport-context)4.2. `TransportContext`
### 4.2. `TransportContext`
One of the key properties of the SOAP protocol is that it tries to be transport-agnostic. This is why, for instance, Spring-WS does not support mapping messages to endpoints by HTTP request URL but rather by message content.
......@@ -925,7 +925,7 @@ HttpServletRequest request = connection.getHttpServletRequest();
String ipAddress = request.getRemoteAddr();
```
### [](#xpath)4.3. Handling XML With XPath
### 4.3. Handling XML With XPath
One of the best ways to handle XML is to use XPath. Quoting [[effective-xml]](#effective-xml), item 35:
......@@ -935,7 +935,7 @@ One of the best ways to handle XML is to use XPath. Quoting [[effective-xml]](#e
Spring Web Services has two ways to use XPath within your application: the faster `XPathExpression` or the more flexible `XPathTemplate`.
#### [](#xpath-expression)4.3.1. `XPathExpression`
#### 4.3.1. `XPathExpression`
The `XPathExpression` is an abstraction over a compiled XPath expression, such as the Java 5 `javax.xml.xpath.XPathExpression` interface or the Jaxen `XPath` class. To construct an expression in an application context, you can use `XPathExpressionFactoryBean`. The following example uses this factory bean:
......@@ -1007,7 +1007,7 @@ public class MyXPathClass {
Similar to mapping rows in Spring JDBC’s `RowMapper`, each result node is mapped by using an anonymous inner class. In this case, we create a `Contact` object, which we use later on.
#### [](#xpath-template)4.3.2. `XPathTemplate`
#### 4.3.2. `XPathTemplate`
The `XPathExpression` lets you evaluate only a single, pre-compiled expression. A more flexible, though slower, alternative is the `XpathTemplate`. This class follows the common template pattern used throughout Spring (`JdbcTemplate`, `JmsTemplate`, and others). The following listing shows an example:
......@@ -1026,7 +1026,7 @@ public class MyXPathClass {
}
```
### [](#logging)4.4. Message Logging and Tracing
### 4.4. Message Logging and Tracing
When developing or debugging a web service, it can be quite useful to look at the content of a (SOAP) message when it arrives or before it is sent. Spring Web Services offer this functionality, through the standard Commons Logging interface.
......@@ -1060,7 +1060,7 @@ DEBUG [server.MessageTracing.sent] Sent response [SaajSoapMessage {http://exampl
DEBUG [client.MessageTracing.received] Received response [SaajSoapMessage {http://example.com}response] ...
```
## [](#server)5. Creating a Web service with Spring-WS
## 5. Creating a Web service with Spring-WS
Spring-WS’s server-side support is designed around a `MessageDispatcher` that dispatches incoming messages to endpoints, with configurable endpoint mappings, response generation, and endpoint interception. Endpoints are typically annotated with the `@Endpoint` annotation and have one or more handling methods. These methods handle incoming XML request messages by inspecting parts of the message (typically the payload) and create some sort of response. You can annotate the method with another annotation, typically `@PayloadRoot`, to indicate what sort of messages it can handle.
......@@ -1074,7 +1074,7 @@ Spring-WS’s XML handling is extremely flexible. An endpoint can choose from a
* Marshalling techniques (JAXB, Castor, XMLBeans, JiBX, or XStream): To convert the XML to objects and vice-versa
### [](#_the_messagedispatcher)5.1. The `MessageDispatcher`
### 5.1. The `MessageDispatcher`
The server-side of Spring-WS is designed around a central class that dispatches incoming XML messages to endpoints. Spring-WS’s `MessageDispatcher` is extremely flexible, letting you use any sort of class as an endpoint, as long as it can be configured in the Spring IoC container. In a way, the message dispatcher resembles Spring’s `DispatcherServlet`, the
“Front Controller” used in Spring Web MVC.
......@@ -1097,11 +1097,11 @@ The `MessageDispatcher` has several properties for setting endpoint adapters, [m
The message dispatcher operates on a [message context](#message-context) and not on a transport-specific input stream and output stream. As a result, transport-specific requests need to read into a `MessageContext`. For HTTP, this is done with a `WebServiceMessageReceiverHandlerAdapter` (which is a Spring Web `HandlerInterceptor`) so that the `MessageDispatcher` can be wired in a standard `DispatcherServlet`. There is a more convenient way to do this, however, which is shown in [`MessageDispatcherServlet`](#message-dispatcher-servlet).
### [](#_transports)5.2. Transports
### 5.2. Transports
Spring Web Services supports multiple transport protocols. The most common is the HTTP transport, for which a custom servlet is supplied, but you can also send messages over JMS and even email.
#### [](#message-dispatcher-servlet)5.2.1. `MessageDispatcherServlet`
#### 5.2.1. `MessageDispatcherServlet`
The `MessageDispatcherServlet` is a standard `Servlet` that conveniently extends from the standard Spring Web `DispatcherServlet` and wraps a `MessageDispatcher`. As a result, it combines the attributes of these into one. As a `MessageDispatcher`, it follows the same request handling flow as described in the previous section. As a servlet, the `MessageDispatcherServlet` is configured in the `web.xml` of your web application. Requests that you want the `MessageDispatcherServlet` to handle must be mapped by a URL mapping in the same `web.xml` file. This is standard Java EE servlet configuration. The following example shows such a `MessageDispatcherServlet` declaration and mapping:
......@@ -1146,7 +1146,7 @@ public class MyServletInitializer
In the preceding example, we tell Spring that endpoint bean definitions can be found in the `MyEndpointConfig` class (which is a `@Configuration` class). Other bean definitions (typically services, repositories, and so on) can be found in the `MyRootConfig` class. By default, the `AbstractAnnotationConfigMessageDispatcherServletInitializer` maps the servlet to two patterns: `/services` and `*.wsdl`, though you can change this by overriding the `getServletMappings()` method. For more details on the programmatic configuration of the `MessageDispatcherServlet`, refer to the Javadoc of [`AbstractMessageDispatcherServletInitializer`](https://docs.spring.io/spring-ws/docs/current/org/springframework/ws/transport/http/support/AbstractMessageDispatcherServletInitializer.html) and [`AbstractAnnotationConfigMessageDispatcherServletInitializer`](https://docs.spring.io/spring-ws/docs/current/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.html).
##### [](#server-automatic-wsdl-exposure)Automatic WSDL exposure
##### Automatic WSDL exposure
The `MessageDispatcherServlet` automatically detects any `WsdlDefinition` beans defined in its Spring container. All the `WsdlDefinition` detected beans are also exposed through a `WsdlDefinitionHandlerAdapter`. This is a convenient way to expose your WSDL to clients by defining some beans.
......@@ -1239,7 +1239,7 @@ To use multiple schemas, either by includes or imports, you can put Commons XMLS
Therefore, you should use `<dynamic-wsdl>` only during the development stages of your project. We recommend using your browser to download the generated WSDL, store it in the project, and expose it with `<static-wsdl>`. This is the only way to be really sure that the WSDL does not change over time.
#### [](#_wiring_up_spring_ws_in_a_dispatcherservlet)5.2.2. Wiring up Spring-WS in a `DispatcherServlet`
#### 5.2.2. Wiring up Spring-WS in a `DispatcherServlet`
As an alternative to the `MessageDispatcherServlet`, you can wire up a `MessageDispatcher` in a standard, Spring-Web MVC `DispatcherServlet`. By default, the `DispatcherServlet` can delegate only to `Controllers`, but we can instruct it to delegate to a `MessageDispatcher` by adding a `WebServiceMessageReceiverHandlerAdapter` to the servlet’s web application context:
......@@ -1292,7 +1292,7 @@ In a similar fashion, you can wire a `WsdlDefinitionHandlerAdapter` to make sure
</beans>
```
#### [](#_jms_transport)5.2.3. JMS transport
#### 5.2.3. JMS transport
Spring Web Services supports server-side JMS handling through the JMS functionality provided in the Spring framework. Spring Web Services provides the `WebServiceMessageListener` to plug in to a `MessageListenerContainer`. This message listener requires a `WebServiceMessageFactory` and `MessageDispatcher` to operate. The following configuration example shows this:
......@@ -1329,7 +1329,7 @@ Spring Web Services supports server-side JMS handling through the JMS functional
</beans>
```
#### [](#_email_transport)5.2.4. Email Transport
#### 5.2.4. Email Transport
In addition to HTTP and JMS, Spring Web Services also provides server-side email handling. This functionality is provided through the `MailMessageReceiver` class. This class monitors a POP3 or IMAP folder, converts the email to a `WebServiceMessage`, and sends any response by using SMTP. You can configure the host names through the `storeUri`, which indicates the mail folder to monitor for requests (typically a POP3 or IMAP folder), and a `transportUri`, which indicates the server to use for sending responses (typically an SMTP server).
......@@ -1370,7 +1370,7 @@ The following piece of configuration shows how to use the server-side email supp
</beans>
```
#### [](#_embedded_http_server_transport)5.2.5. Embedded HTTP Server transport
#### 5.2.5. Embedded HTTP Server transport
Spring Web Services provides a transport based on Sun’s JRE 1.6 [HTTP server](http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/index.html). The embedded HTTP Server is a standalone server that is simple to configure. It offers a lighter alternative to conventional servlet containers.
......@@ -1417,7 +1417,7 @@ The following snippet shows a configuration example of the HTTP server transport
For more information on the `SimpleHttpServerFactoryBean`, see the [Javadoc](http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/remoting/support/SimpleHttpServerFactoryBean.html).
#### [](#_xmpp_transport)5.2.6. XMPP transport
#### 5.2.6. XMPP transport
Spring Web Services 2.0 introduced support for XMPP, otherwise known as Jabber. The support is based on the [Smack](https://www.igniterealtime.org/projects/smack/index.jsp) library.
......@@ -1456,11 +1456,11 @@ The following example shows how to set up the server-side XMPP components:
</beans>
```
#### [](#_mtom)5.2.7. MTOM
#### 5.2.7. MTOM
[MTOM](https://en.wikipedia.org/wiki/Message_Transmission_Optimization_Mechanism) is the mechanism for sending binary data to and from Web Services. You can look at how to implement this with Spring WS through the [MTOM sample](https://github.com/spring-projects/spring-ws-samples/tree/main/mtom).
### [](#server-endpoints)5.3. Endpoints
### 5.3. Endpoints
Endpoints are the central concept in Spring-WS’s server-side support. Endpoints provide access to the application behavior, which is typically defined by a business service interface. An endpoint interprets the XML request message and uses that input to (typically) invoke a method on the business service. The result of that service invocation is represented as a response message. Spring-WS has a wide variety of endpoints and uses various ways to handle the XML message and to create a response.
......@@ -1572,7 +1572,7 @@ In the next couple of sections, a more elaborate description of the `@Endpoint`
Note that all abstract base classes provided in Spring-WS are thread safe, unless otherwise indicated in the class-level Javadoc.
```
#### [](#server-atEndpoint-methods)5.3.1. `@Endpoint` handling methods
#### 5.3.1. `@Endpoint` handling methods
For an endpoint to actually handle incoming XML messages, it needs to have one or more handling methods. Handling methods can take wide range of parameters and return types. However, they typically have one parameter that contains the message payload, and they return the payload of the response message (if any). This section covers which parameter and return types are supported.
......@@ -1590,7 +1590,7 @@ public void order(@RequestPayload Element orderElement) {
The `order` method takes an `Element` (annotated with `@RequestPayload`) as a parameter. This means that the payload of the message is passed on this method as a DOM element. The method has a `void` return type, indicating that no response message is sent.
##### [](#_handling_method_parameters)Handling Method Parameters
##### Handling Method Parameters
The handling method typically has one or more parameters that refer to various parts of the incoming XML message. Most commonly, the handling method has a single parameter that maps to the payload of the message, but it can also map to other parts of the request message, such as a SOAP header. This section describes the parameters you can use in your handling method signatures.
......@@ -1632,7 +1632,7 @@ public void handle(@RequestPayload MyJaxb2Object requestObject, @RequestPayload
As you can see, there are a lot of possibilities when it comes to defining how to handle method signatures. You can even extend this mechanism to support your own parameter types. See the Javadoc of [`DefaultMethodEndpointAdapter`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.html) and [`MethodArgumentResolver`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.html) to see how.
###### [](#server-xpath-param)`@XPathParam`
###### `@XPathParam`
One parameter type needs some extra explanation: `@XPathParam`. The idea here is that you annotate one or more method parameters with an XPath expression and that each such annotated parameter is bound to the evaluation of the expression. The following example shows how to do so:
......@@ -1681,7 +1681,7 @@ By using the `@XPathParam`, you can bind to all the data types supported by XPat
In addition to this list, you can use any type that can be converted from a `String` by a Spring [conversion service](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#core-convert-ConversionService-API).
##### [](#_handling_method_return_types)Handling method return types
##### Handling method return types
To send a response message, the handling needs to specify a return type. If no response message is required, the method can declare a `void` return type. Most commonly, the return type is used to create the payload of the response message. However, you can also map to other parts of the response message. This section describes the return types you can use in your handling method signatures.
......@@ -1702,7 +1702,7 @@ The following table describes the supported return types. It shows the supported
There are a lot of possibilities when it comes to defining handling method signatures. It is even possible to extend this mechanism to support your own parameter types. See the class-level Javadoc of [`DefaultMethodEndpointAdapter`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.html) and [`MethodReturnValueHandler`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.html) to see how.
### [](#server-endpoint-mapping)5.4. Endpoint mappings
### 5.4. Endpoint mappings
The endpoint mapping is responsible for mapping incoming messages to appropriate endpoints. Some endpoint mappings are enabled by default — for example, the `PayloadRootAnnotationMethodEndpointMapping` or the `SoapActionAnnotationMethodEndpointMapping`. However, we first need to examine the general concept of an `EndpointMapping`.
......@@ -1720,7 +1720,7 @@ The `PayloadRootAnnotationMethodEndpointMapping` uses the `@PayloadRoot` annotat
Alternatively, the `SoapActionAnnotationMethodEndpointMapping` uses the `@SoapAction` annotation to mark methods with a particular SOAP Action. Whenever a message comes in with this `SOAPAction` header, the method is invoked.
#### [](#server-ws-addressing)5.4.1. WS-Addressing
#### 5.4.1. WS-Addressing
WS-Addressing specifies a transport-neutral routing mechanism. It is based on the `To` and `Action` SOAP headers, which indicate the destination and intent of the SOAP message, respectively. Additionally, WS-Addressing lets you define a return address (for normal messages and for faults) and a unique message identifier, which can be used for correlation. For more information on WS-Addressing, see [https://en.wikipedia.org/wiki/WS-Addressing](https://en.wikipedia.org/wiki/WS-Addressing). The following example shows a WS-Addressing message:
......@@ -1747,7 +1747,7 @@ In the preceding example, the destination is set to `[http://example/com/fabrika
In Spring Web Services, WS-Addressing is implemented as an endpoint mapping. By using this mapping, you associate WS-Addressing actions with endpoints, similar to the `SoapActionAnnotationMethodEndpointMapping` described earlier.
##### [](#_using_annotationactionendpointmapping)Using `AnnotationActionEndpointMapping`
##### Using `AnnotationActionEndpointMapping`
The `AnnotationActionEndpointMapping` is similar to the `SoapActionAnnotationMethodEndpointMapping` but uses WS-Addressing headers instead of the SOAP Action transport header.
......@@ -1788,7 +1788,7 @@ In addition to the `@Action` annotation, you can annotate the class with the `@A
Finally, there is the `messageSenders` property, which is required for sending response messages to non-anonymous, out-of-bound addresses. You can set `MessageSender` implementations in this property, the same as you would on the `WebServiceTemplate`. See [URIs and Transports](#client-transports).
#### [](#server-endpoint-interceptor)5.4.2. Intercepting Requests — the `EndpointInterceptor` Interface
#### 5.4.2. Intercepting Requests — the `EndpointInterceptor` Interface
The endpoint mapping mechanism has the notion of endpoint interceptors. These can be extremely useful when you want to apply specific functionality to certain requests — for example, dealing with security-related SOAP headers or the logging of request and response message.
......@@ -1832,7 +1832,7 @@ The `handleRequest(..)` method on the interceptor returns a boolean value. You c
There are a number of standard `EndpointInterceptor` implementations that you can use in your Web service. Additionally, there is the `XwsSecurityInterceptor`, which is described in [`XwsSecurityInterceptor`](#security-xws-security-interceptor).
##### [](#_payloadlogginginterceptor_and_soapenvelopelogginginterceptor)`PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor`
##### `PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor`
When developing a web service, it can be useful to log the incoming and outgoing XML messages. Spring WS facilitates this with the `PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor` classes. The former logs only the payload of the message to the Commons Logging Log. The latter logs the entire SOAP envelope, including SOAP headers. The following example shows how to define the `PayloadLoggingInterceptor` in an endpoint mapping:
......@@ -1846,7 +1846,7 @@ Both of these interceptors have two properties, `logRequest` and `logResponse`,
You could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadLoggingInterceptor` as well.
##### [](#_payloadvalidatinginterceptor)`PayloadValidatingInterceptor`
##### `PayloadValidatingInterceptor`
One of the benefits of using a contract-first development style is that we can use the schema to validate incoming and outgoing XML messages. Spring-WS facilitates this with the `PayloadValidatingInterceptor`. This interceptor requires a reference to one or more W3C XML or RELAX NG schemas and can be set to validate requests, responses, or both.
......@@ -1866,7 +1866,7 @@ The following example uses the `PayloadValidatingInterceptor`. In this example,
Of course, you could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadValidatingInterceptor` as well.
##### [](#_using_payloadtransforminginterceptor)Using `PayloadTransformingInterceptor`
##### Using `PayloadTransformingInterceptor`
To transform the payload to another XML format, Spring Web Services offers the `PayloadTransformingInterceptor`. This endpoint interceptor is based on XSLT style sheets and is especially useful when supporting multiple versions of a web service, because you can transform the older message format to the newer format. The following example uses the `PayloadTransformingInterceptor`:
......@@ -1882,7 +1882,7 @@ In the preceding example, we transform requests by using `/WEB-INF/oldRequests.x
You could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadTransformingInterceptor` as well.
### [](#server-endpoint-exception-resolver)5.5. Handling Exceptions
### 5.5. Handling Exceptions
Spring-WS provides `EndpointExceptionResolvers` to ease the pain of unexpected exceptions occurring while your message is being processed by an endpoint that matched the request. Endpoint exception resolvers somewhat resemble the exception mappings that can be defined in the web application descriptor `web.xml`. However, they provide a more flexible way to handle exceptions. They provide information about what endpoint was invoked when the exception was thrown. Furthermore, a programmatic way of handling exceptions gives you many more options for how to respond appropriately. Rather than expose the innards of your application by giving an exception and stack trace, you can handle the exception any way you want — for example, by returning a SOAP fault with a specific fault code and string.
......@@ -1890,7 +1890,7 @@ Endpoint exception resolvers are automatically picked up by the `MessageDispatch
Besides implementing the `EndpointExceptionResolver` interface, which is only a matter of implementing the `resolveException(MessageContext, endpoint, Exception)` method, you may also use one of the provided implementations. The simplest implementation is the `SimpleSoapExceptionResolver`, which creates a SOAP 1.1 Server or SOAP 1.2 Receiver fault and uses the exception message as the fault string. The `SimpleSoapExceptionResolver` is the default, but it can be overridden by explicitly adding another resolver.
#### [](#_soapfaultmappingexceptionresolver)5.5.1. `SoapFaultMappingExceptionResolver`
#### 5.5.1. `SoapFaultMappingExceptionResolver`
The `SoapFaultMappingExceptionResolver` is a more sophisticated implementation. This resolver lets you take the class name of any exception that might be thrown and map it to a SOAP Fault:
......@@ -1923,7 +1923,7 @@ The key values and default endpoint use a format of `faultCode,faultString,local
If any other exception occurs, it returns the default fault: a server-side fault with the exception message as the fault string.
#### [](#_using_soapfaultannotationexceptionresolver)5.5.2. Using `SoapFaultAnnotationExceptionResolver`
#### 5.5.2. Using `SoapFaultAnnotationExceptionResolver`
You can also annotate exception classes with the `@SoapFault` annotation, to indicate the SOAP fault that should be returned whenever that exception is thrown. For these annotations to be picked up, you need to add the `SoapFaultAnnotationExceptionResolver` to your application context. The elements of the annotation include a fault code enumeration, fault string or reason, and language. The following example shows such an exception:
......@@ -1955,7 +1955,7 @@ Whenever the `MyBusinessException` is thrown with the constructor string `"Oops!
</SOAP-ENV:Envelope>
```
### [](#_server_side_testing)5.6. Server-side Testing
### 5.6. Server-side Testing
When it comes to testing your Web service endpoints, you have two possible approaches:
......@@ -1967,7 +1967,7 @@ When it comes to testing your Web service endpoints, you have two possible appro
The first approach can easily be accomplished with mocking frameworks such as EasyMock, JMock, and others. The next section focuses on writing integration tests, using the test features introduced in Spring Web Services 2.0.
#### [](#_writing_server_side_integration_tests)5.6.1. Writing server-side integration tests
#### 5.6.1. Writing server-side integration tests
Spring Web Services 2.0 introduced support for creating endpoint integration tests. In this context, an endpoint is a class that handles (SOAP) messages (see [Endpoints](#server-endpoints)).
......@@ -2068,7 +2068,7 @@ public class CustomerEndpointIntegrationTest {
|**4**| In a `@Before` method, we create a `MockWebServiceClient` by using the `createClient` factory method. |
|**5**|We send a request by calling `sendRequest()` with a `withPayload()` `RequestCreator` provided by the statically imported `RequestCreators` (see [Using `RequestCreator` and `RequestCreators`](#server-test-request-creator)).<br/><br/>We also set up response expectations by calling `andExpect()` with a `payload()` `ResponseMatcher` provided by the statically imported `ResponseMatchers` (see [Using `ResponseMatcher` and `ResponseMatchers`](#server-test-response-matcher)).<br/><br/>This part of the test might look a bit confusing, but the code completion features of your IDE are of great help. After typing `sendRequest(`, your IDE can provide you with a list of possible request creating strategies, provided you statically imported `RequestCreators`. The same applies to `andExpect()`, provided you statically imported `ResponseMatchers`.|
#### [](#server-test-request-creator)5.6.2. Using `RequestCreator` and `RequestCreators`
#### 5.6.2. Using `RequestCreator` and `RequestCreators`
Initially, the `MockWebServiceClient` needs to create a request message for the endpoint to consume. The client uses the `RequestCreator` strategy interface for this purpose:
......@@ -2083,7 +2083,7 @@ public interface RequestCreator {
You can write your own implementations of this interface, creating a request message by using the message factory, but you certainly do not have to. The `RequestCreators` class provides a way to create a `RequestCreator` based on a given payload in the `withPayload()` method. You typically statically import `RequestCreators`.
#### [](#server-test-response-matcher)5.6.3. Using `ResponseMatcher` and `ResponseMatchers`
#### 5.6.3. Using `ResponseMatcher` and `ResponseMatchers`
When the request message has been processed by the endpoint and a response has been received, the `MockWebServiceClient` can verify whether this response message meets certain expectations. The client uses the `ResponseMatcher` strategy interface for this purpose:
......@@ -2120,7 +2120,7 @@ mockClient.sendRequest(...).
For more information on the response matchers provided by `ResponseMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/server/ResponseMatchers.html).
## [](#client)6. Using Spring Web Services on the Client
## 6. Using Spring Web Services on the Client
Spring-WS provides a client-side Web service API that allows for consistent, XML-driven access to web services. It also caters to the use of marshallers and unmarshallers so that your service-tier code can deal exclusively with Java objects.
......@@ -2132,19 +2132,19 @@ The `org.springframework.ws.client.core` package provides the core functionality
* Allowing for multiple transport options
### [](#_using_the_client_side_api)6.1. Using the Client-side API
### 6.1. Using the Client-side API
This section describs how to use the client-side API. For how to use the server-side API, see [Creating a Web service with Spring-WS](#server).
#### [](#client-web-service-template)6.1.1. `WebServiceTemplate`
#### 6.1.1. `WebServiceTemplate`
The `WebServiceTemplate` is the core class for client-side web service access in Spring-WS. It contains methods for sending `Source` objects and receiving response messages as either `Source` or `Result`. Additionally, it can marshal objects to XML before sending them across a transport and unmarshal any response XML into an object again.
##### [](#client-transports)URIs and Transports
##### URIs and Transports
The `WebServiceTemplate` class uses an URI as the message destination. You can either set a `defaultUri` property on the template itself or explicitly supply a URI when calling a method on the template. The URI is resolved into a `WebServiceMessageSender`, which is responsible for sending the XML message across a transport layer. You can set one or more message senders by using the `messageSender` or `messageSenders` properties of the `WebServiceTemplate` class.
###### [](#_http_transports)HTTP transports
###### HTTP transports
There are two implementations of the `WebServiceMessageSender` interface for sending messages over HTTP. The default implementation is the `HttpUrlConnectionMessageSender`, which uses the facilities provided by Java itself. The alternative is the `HttpComponentsMessageSender`, which uses the [Apache HttpComponents HttpClient](https://hc.apache.org/httpcomponents-client-ga). Use the latter if you need more advanced and easy-to-use functionality (such as authentication, HTTP connection pooling, and so forth).
......@@ -2183,7 +2183,7 @@ The following example shows how to override the default configuration and how to
</bean>
```
###### [](#_jms_transport_2)JMS transport
###### JMS transport
For sending messages over JMS, Spring Web Services provides `JmsMessageSender`. This class uses the facilities of the Spring framework to transform the `WebServiceMessage` into a JMS `Message`, send it on its way on a `Queue` or `Topic`, and receive a response (if any).
......@@ -2215,7 +2215,7 @@ The following example shows how to use the JMS transport in combination with an
</beans>
```
###### [](#_email_transport_2)Email Transport
###### Email Transport
Spring Web Services also provides an email transport, which you can use to send web service messages over SMTP and retrieve them over either POP3 or IMAP. The client-side email functionality is contained in the `MailMessageSender` class. This class creates an email message from the request `WebServiceMessage` and sends it over SMTP. It then waits for a response message to arrive at the incoming POP3 or IMAP server.
......@@ -2243,7 +2243,7 @@ The following example shows how to use the email transport:
</beans>
```
###### [](#_xmpp_transport_2)XMPP Transport
###### XMPP Transport
Spring Web Services 2.0 introduced an XMPP (Jabber) transport, which you can use to send and receive web service messages over XMPP. The client-side XMPP functionality is contained in the `XmppMessageSender` class. This class creates an XMPP message from the request `WebServiceMessage` and sends it over XMPP. It then listens for a response message to arrive.
......@@ -2275,11 +2275,11 @@ The following example shows how to use the XMPP transport:
</beans>
```
##### [](#_message_factories)Message factories
##### Message factories
In addition to a message sender, the `WebServiceTemplate` requires a web service message factory. There are two message factories for SOAP: `SaajSoapMessageFactory` and `AxiomSoapMessageFactory`. If no message factory is specified (by setting the `messageFactory` property), Spring-WS uses the `SaajSoapMessageFactory` by default.
#### [](#_sending_and_receiving_a_webservicemessage)6.1.2. Sending and Receiving a `WebServiceMessage`
#### 6.1.2. Sending and Receiving a `WebServiceMessage`
The `WebServiceTemplate` contains many convenience methods to send and receive web service messages. There are methods that accept and return a `Source` and those that return a `Result`. Additionally, there are methods that marshal and unmarshal objects to XML. The following example sends a simple XML message to a web service:
......@@ -2335,11 +2335,11 @@ The preceding example uses the `WebServiceTemplate` to send a “Hello, World”
Note that the `WebServiceTemplate` class is thread-safe once configured (assuming that all of its dependencies are also thread-safe, which is the case for all of the dependencies that ship with Spring-WS), so multiple objects can use the same shared `WebServiceTemplate` instance. The `WebServiceTemplate` exposes a zero-argument constructor and `messageFactory` and `messageSender` bean properties that you can use to construct the instance (by using a Spring container or plain Java code). Alternatively, consider deriving from Spring-WS’s `WebServiceGatewaySupport` convenience base class, which exposes convenient bean properties to enable easy configuration. (You do not have to extend this base class. It is provided as a convenience class only.)
#### [](#_sending_and_receiving_pojosmarshalling_and_unmarshalling)6.1.3. Sending and Receiving POJOs — Marshalling and Unmarshalling
#### 6.1.3. Sending and Receiving POJOs — Marshalling and Unmarshalling
To facilitate the sending of plain Java objects, the `WebServiceTemplate` has a number of `send(..)` methods that take an `Object` as an argument for a message’s data content. The method `marshalSendAndReceive(..)` in the `WebServiceTemplate` class delegates the conversion of the request object to XML to a `Marshaller` and the conversion of the response XML to an object to an `Unmarshaller`. (For more information about marshalling and unmarshaller, see [the Spring Framework reference documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#oxm-marshaller-unmarshaller).) By using the marshallers, your application code can focus on the business object that is being sent or received and not be concerned with the details of how it is represented as XML. To use the marshalling functionality, you have to set a marshaller and an unmarshaller with the `marshaller` and `unmarshaller` properties of the `WebServiceTemplate` class.
#### [](#_using_webservicemessagecallback)6.1.4. Using `WebServiceMessageCallback`
#### 6.1.4. Using `WebServiceMessageCallback`
To accommodate setting SOAP headers and other settings on the message, the `WebServiceMessageCallback` interface gives you access to the message after it has been created but before it is sent. The following example demonstrates how to set the SOAP action header on a message that is created by marshalling an object:
......@@ -2358,7 +2358,7 @@ public void marshalWithSoapActionHeader(MyObject o) {
| |Note that you can also use the `org.springframework.ws.soap.client.core.SoapActionCallback` to set the SOAP action header.|
|---|--------------------------------------------------------------------------------------------------------------------------|
##### [](#_ws_addressing)WS-Addressing
##### WS-Addressing
In addition to the [server-side WS-Addressing](#server-ws-addressing) support, Spring Web Services also has support for this specification on the client-side.
......@@ -2370,7 +2370,7 @@ The following example sets the `Action` header to `[http://samples/RequestOrder]
webServiceTemplate.marshalSendAndReceive(o, new ActionCallback("http://samples/RequestOrder"));
```
#### [](#_using_webservicemessageextractor)6.1.5. Using `WebServiceMessageExtractor`
#### 6.1.5. Using `WebServiceMessageExtractor`
The `WebServiceMessageExtractor` interface is a low-level callback interface that you have full control over the process to extract an `Object` from a received `WebServiceMessage`. The `WebServiceTemplate` invokes the `extractData(..)` method on a supplied `WebServiceMessageExtractor` while the underlying connection to the serving resource is still open. The following example shows the `WebServiceMessageExtractor` in action:
......@@ -2391,7 +2391,7 @@ public void marshalWithSoapActionHeader(final Source s) {
}
```
### [](#_client_side_testing)6.2. Client-side Testing
### 6.2. Client-side Testing
When it comes to testing your Web service clients (that is, classes that use the `WebServiceTemplate` to access a Web service), you have two possible approaches:
......@@ -2403,7 +2403,7 @@ When it comes to testing your Web service clients (that is, classes that use the
The first approach can easily be accomplished with mocking frameworks, such as EasyMock, JMock, and others. The next section focuses on writing integration tests, using the test features introduced in Spring Web Services 2.0.
#### [](#_writing_client_side_integration_tests)6.2.1. Writing Client-side Integration Tests
#### 6.2.1. Writing Client-side Integration Tests
Spring Web Services 2.0 introduced support for creating Web service client integration tests. In this context, a client is a class that uses the `WebServiceTemplate` to access a web service.
......@@ -2516,7 +2516,7 @@ public class CustomerClientIntegrationTest {
|**6**| We call `getCustomerCount()` on the `CustomerClient`, thus using the `WebServiceTemplate`. The template has been set up for “testing mode” by now, so no real (HTTP) connection is made by this method call. We also make some JUnit assertions based on the result of the method call. |
|**7**| We call `verify()` on the `MockWebServiceServer`, verifying that the expected message was actually received. |
#### [](#client-test-request-matcher)6.2.2. Using `RequestMatcher` and `RequestMatchers`
#### 6.2.2. Using `RequestMatcher` and `RequestMatchers`
To verify whether the request message meets certain expectations, the `MockWebServiceServer` uses the `RequestMatcher` strategy interface. The contract defined by this interface is as follows:
......@@ -2554,7 +2554,7 @@ mockServer.expect(connectionTo("http://example.com")).
For more information on the request matchers provided by `RequestMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html).
#### [](#client-test-response-creator)6.2.3. Using `ResponseCreator` and `ResponseCreators`
#### 6.2.3. Using `ResponseCreator` and `ResponseCreators`
When the request message has been verified and meets the defined expectations, the `MockWebServiceServer` creates a response message for the `WebServiceTemplate` to consume. The server uses the `ResponseCreator` strategy interface for this purpose:
......@@ -2582,7 +2582,7 @@ The `ResponseCreators` class provides the following responses:
For more information on the request matchers provided by `RequestMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html).
## [](#security)7. Securing Your Web services with Spring-WS
## 7. Securing Your Web services with Spring-WS
This chapter explains how to add WS-Security aspects to your Web services. We focus on the three different areas of WS-Security:
......@@ -2597,7 +2597,7 @@ These three areas are implemented by using the `XwsSecurityInterceptor` or `Wss4
| |Note that WS-Security (especially encryption and signing) requires substantial amounts of memory and can decrease performance. If performance is important to you, you might want to consider not using WS-Security or using HTTP-based security.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#security-xws-security-interceptor)7.1. `XwsSecurityInterceptor`
### 7.1. `XwsSecurityInterceptor`
The `XwsSecurityInterceptor` is an `EndpointInterceptor` (see [Intercepting Requests — the `EndpointInterceptor` Interface](#server-endpoint-interceptor)) that is based on SUN’s XML and Web Services Security package (XWSS). This WS-Security implementation is part of the Java Web Services Developer Pack ([Java WSDP](http://java.sun.com/webservices/)).
......@@ -2630,7 +2630,7 @@ The following example that shows how to wire up the `XwsSecurityInterceptor`:
This interceptor is configured by using the `securityPolicy.xml` file on the classpath. It uses two callback handlers that are defined later in the file.
#### [](#keystore)7.1.1. Keystores
#### 7.1.1. Keystores
For most cryptographic operations, you an use the standard `java.security.KeyStore` objects. These operations include certificate verification, message signing, signature verification, and encryption. They exclude username and time-stamp verification. This section aims to give you some background knowledge on keystores and the Java tools that you can use to store keys and certificates in a keystore file. This information is mostly not related to Spring-WS but to the general cryptographic features of Java.
......@@ -2642,11 +2642,11 @@ The `java.security.KeyStore` class represents a storage facility for cryptograph
* **Trusted certificates**: These X509 certificates are called a “trusted certificate” because the keystore owner trusts that the public key in the certificates does indeed belong to the owner of the certificate. Within WS-Security, these certificates are used for certificate validation, signature verification, and encryption.
##### [](#_using_keytool)Using `keytool`
##### Using `keytool`
The `keytool` program, a key and certificate management utility, is supplied with your Java Virtual Machine. You can use this tool to create new keystores, add new private keys and certificates to them, and so on. It is beyond the scope of this document to provide a full reference of the `keytool` command, but you can find a reference [here](http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/keytool.html) or by using the `keytool -help` command on the command line.
##### [](#_using_keystorefactorybean)Using `KeyStoreFactoryBean`
##### Using `KeyStoreFactoryBean`
To easily load a keystore by using Spring configuration, you can use the `KeyStoreFactoryBean`. It has a resource location property, which you can set to point to the path of the keystore to load. A password may be given to check the integrity of the keystore data. If a password is not given, integrity checking is not performed. The following listing configures a `KeyStoreFactoryBean`:
......@@ -2660,7 +2660,7 @@ To easily load a keystore by using Spring configuration, you can use the `KeySto
| |If you do not specify the location property, a new, empty keystore is created, which is most likely not what you want.|
|---|----------------------------------------------------------------------------------------------------------------------|
##### [](#security-key-store-callback-handler)KeyStoreCallbackHandler
##### KeyStoreCallbackHandler
To use the keystores within a `XwsSecurityInterceptor`, you need to define a `KeyStoreCallbackHandler`. This callback has three properties with type `keystore`: (`keyStore`,`trustStore`, and `symmetricStore`). The exact stores used by the handler depend on the cryptographic operations that are to be performed by this handler. For private key operation, the `keyStore` is used. For symmetric key operations, the `symmetricStore` is used. For determining trust relationships, the `trustStore` is used. The following table indicates this:
......@@ -2711,11 +2711,11 @@ If you want to use it to decrypt incoming certificates or sign outgoing messages
The following sections indicate where the `KeyStoreCallbackHandler` can be used and which properties to set for particular cryptographic operations.
#### [](#_authentication)7.1.2. Authentication
#### 7.1.2. Authentication
As stated in the [introduction to this chapter](#security), authentication is the task of determining whether a principal is who they claim to be. Within WS-Security, authentication can take two forms: using a username and password token (using either a plain text password or a password digest) or using a X509 certificate.
##### [](#_plain_text_username_authentication)Plain Text Username Authentication
##### Plain Text Username Authentication
The simplest form of username authentication uses plain text passwords. In this scenario, the SOAP message contains a `UsernameToken` element, which itself contains a `Username` element and a `Password` element which contains the plain text password. Plain text authentication can be compared to the basic authentication provided by HTTP servers.
......@@ -2740,7 +2740,7 @@ If the username token is not present, the `XwsSecurityInterceptor` returns a SOA
* [`JaasPlainTextPasswordValidationCallbackHandler`](#using-jaasplaintextpasswordvalidationcallbackhandler)
###### [](#security-simple-password-validation-callback-handler)Using `SimplePasswordValidationCallbackHandler`
###### Using `SimplePasswordValidationCallbackHandler`
The simplest password validation handler is the `SimplePasswordValidationCallbackHandler`. This handler validates passwords against an in-memory `Properties` object, which you can specify byusing the `users` property:
......@@ -2757,7 +2757,7 @@ The simplest password validation handler is the `SimplePasswordValidationCallbac
In this case, we are allowing only the user, "Bert", to log in by using the password, "Ernie".
###### [](#using-springplaintextpasswordvalidationcallbackhandler)Using `SpringPlainTextPasswordValidationCallbackHandler`
###### Using `SpringPlainTextPasswordValidationCallbackHandler`
The `SpringPlainTextPasswordValidationCallbackHandler` uses [Spring Security](https://spring.io/projects/spring-security) to authenticate users. It is beyond the scope of this document to describe Spring Security, but it is a full-fledged security framework. You can read more about it in the [Spring Security reference documentation](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/).
......@@ -2783,7 +2783,7 @@ The `SpringPlainTextPasswordValidationCallbackHandler` requires an `Authenticati
</beans>
```
###### [](#using-jaasplaintextpasswordvalidationcallbackhandler)Using `JaasPlainTextPasswordValidationCallbackHandler`
###### Using `JaasPlainTextPasswordValidationCallbackHandler`
The `JaasPlainTextPasswordValidationCallbackHandler` is based on the standard [Java Authentication and Authorization Service](http://java.sun.com/products/jaas/). It is beyond the scope of this document to provide a full introduction into JAAS, but a [good tutorial](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html) is available.
......@@ -2800,7 +2800,7 @@ You can wire up a `JaasPlainTextPasswordValidationCallbackHandler` as follows:
In this case, the callback handler uses the `LoginContext` named `MyLoginModule`. This module should be defined in your `jaas.config` file, as explained in the [tutorial mentioned earlier](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html).
##### [](#_digest_username_authentication)Digest Username Authentication
##### Digest Username Authentication
When using password digests, the SOAP message also contains a `UsernameToken` element, which itself contains a `Username` element and a `Password` element. The difference is that the password is not sent as plain text, but as a digest. The recipient compares this digest to the digest he calculated from the known password of the user, and, if they are the same, the user is authenticated. This method is comparable to the digest authentication provided by HTTP servers.
......@@ -2816,11 +2816,11 @@ To require that every incoming message contains a `UsernameToken` element with a
If the username token is not present, the `XwsSecurityInterceptor` returns a SOAP fault to the sender. If it is present, it fires a `PasswordValidationCallback` with a `DigestPasswordRequest` to the registered handlers. Within Spring-WS, two classes handle this particular callback: `SimplePasswordValidationCallbackHandler` and `SpringDigestPasswordValidationCallbackHandler`.
###### [](#_using_simplepasswordvalidationcallbackhandler)Using `SimplePasswordValidationCallbackHandler`
###### Using `SimplePasswordValidationCallbackHandler`
The `SimplePasswordValidationCallbackHandler` can handle both plain text passwords as well as password digests. It is described in [Using `SimplePasswordValidationCallbackHandler`](#security-simple-password-validation-callback-handler).
###### [](#_using_springdigestpasswordvalidationcallbackhandler)Using `SpringDigestPasswordValidationCallbackHandler`
###### Using `SpringDigestPasswordValidationCallbackHandler`
The `SpringDigestPasswordValidationCallbackHandler` requires a Spring Security `UserDetailService` to operate. It uses this service to retrieve the password of the user specified in the token. The digest of the password contained in this details object is then compared with the digest in the message. If they are equal, the user has successfully authenticated, and a `UsernamePasswordAuthenticationToken` is stored in the `SecurityContextHolder`. You can set the service by using the `userDetailsService` property. Additionally, you can set a `userCache` property, to cache loaded user details. The following example shows how to do so:
......@@ -2835,7 +2835,7 @@ The `SpringDigestPasswordValidationCallbackHandler` requires a Spring Security `
</beans>
```
##### [](#security-certificate-authentication)Certificate Authentication
##### Certificate Authentication
A more secure way of authentication uses X509 certificates. In this scenario, the SOAP message contains a`BinarySecurityToken`, which contains a Base 64-encoded version of a X509 certificate. The certificate is used by the recipient to authenticate. The certificate stored in the message is also used to sign the message (see [Verifying Signatures](#security-verifying-signatures)).
......@@ -2860,7 +2860,7 @@ When a message arrives that carries no certificate, the `XwsSecurityInterceptor`
| |In most cases, certificate authentication should be preceded by certificate validation, since you want to authenticate against only valid certificates. Invalid certificates, such as certificates for which the expiration date has passed or which are not in your store of trusted certificates, should be ignored.<br/><br/>In Spring-WS terms, this means that the `SpringCertificateValidationCallbackHandler` or `JaasCertificateValidationCallbackHandler` should be preceded by `KeyStoreCallbackHandler`. This can be accomplished by setting the order of the `callbackHandlers` property in the configuration of the `XwsSecurityInterceptor`:<br/><br/>```<br/><bean id="wsSecurityInterceptor"<br/> class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"><br/> <property name="policyConfiguration" value="classpath:securityPolicy.xml"/><br/> <property name="callbackHandlers"><br/> <list><br/> <ref bean="keyStoreHandler"/><br/> <ref bean="springSecurityHandler"/><br/> </list><br/> </property><br/></bean><br/>```<br/><br/>Using this setup, the interceptor first determines if the certificate in the message is valid buusing the keystore and then authenticating against it.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
###### [](#using-keystorecallbackhandler)Using `KeyStoreCallbackHandler`
###### Using `KeyStoreCallbackHandler`
The `KeyStoreCallbackHandler` uses a standard Java keystore to validate certificates. This certificate validation process consists of the following steps: .
......@@ -2887,7 +2887,7 @@ To use the `KeyStoreCallbackHandler` for certificate validation purposes, you mo
Using the setup shown in the preceding example, the certificate that is to be validated must be in the trust store itself or the trust store must contain a certificate authority that issued the certificate.
###### [](#using-springcertificatevalidationcallbackhandler)Using `SpringCertificateValidationCallbackHandler`
###### Using `SpringCertificateValidationCallbackHandler`
The `SpringCertificateValidationCallbackHandler` requires an Spring Security `AuthenticationManager` to operate. It uses this manager to authenticate against a `X509AuthenticationToken` that it creates. The configured authentication manager is expected to supply a provider that can handle this token (usually an instance of `X509AuthenticationProvider`). If authentication is successful, the token is stored in the `SecurityContextHolder`. You can set the authentication manager by using the `authenticationManager` property:
......@@ -2918,7 +2918,7 @@ The `SpringCertificateValidationCallbackHandler` requires an Spring Security `Au
In this case, we use a custom user details service to obtain authentication details based on the certificate. See the [Spring Security reference documentation](http://www.springframework.org/security) for more information about authentication against X509 certificates.
###### [](#using-jaascertificatevalidationcallbackhandler)Using `JaasCertificateValidationCallbackHandler`
###### Using `JaasCertificateValidationCallbackHandler`
The `JaasCertificateValidationCallbackHandler` requires a `loginContextName` to operate. It creates a new JAAS `LoginContext` by using this name and the `X500Principal` of the certificate. This means that this callback handler integrates with any JAAS `LoginModule` that handles X500 principals.
......@@ -2933,11 +2933,11 @@ You can wire up a `JaasCertificateValidationCallbackHandler` as follows:
In this case, the callback handler uses the `LoginContext` named `MyLoginModule`. This module should be defined in your `jaas.config` file and should be able to authenticate against X500 principals.
#### [](#_digital_signatures)7.1.3. Digital Signatures
#### 7.1.3. Digital Signatures
The digital signature of a message is a piece of information based on both the document and the signer’s private key. Two main tasks are related to signatures in WS-Security: verifying signatures and signing messages.
##### [](#security-verifying-signatures)Verifying Signatures
##### Verifying Signatures
As with [certificate-based authentication](#security-certificate-authentication), a signed message contains a `BinarySecurityToken`, which contains the certificate used to sign the message. Additionally, it contains a `SignedInfo` block, which indicates what part of the message was signed.
......@@ -2951,7 +2951,7 @@ To make sure that all incoming SOAP messages carry a `BinarySecurityToken`, the
If the signature is not present, the `XwsSecurityInterceptor` returns a SOAP fault to the sender. If it is present, it fires a `SignatureVerificationKeyCallback` to the registered handlers. Within Spring-WS, one class handles this particular callback: `KeyStoreCallbackHandler`.
###### [](#_using_keystorecallbackhandler)Using `KeyStoreCallbackHandler`
###### Using `KeyStoreCallbackHandler`
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), `KeyStoreCallbackHandler` uses a `java.security.KeyStore` for handling various cryptographic callbacks, including signature verification. For signature verification, the handler uses the `trustStore` property:
......@@ -2968,7 +2968,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
##### [](#_signing_messages)Signing Messages
##### Signing Messages
When signing a message, the `XwsSecurityInterceptor` adds the `BinarySecurityToken` to the message. It also adds a `SignedInfo` block, which indicates what part of the message was signed.
......@@ -2982,7 +2982,7 @@ To sign all outgoing SOAP messages, the security policy file should contain a `S
The `XwsSecurityInterceptor` fires a `SignatureKeyCallback` to the registered handlers. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
###### [](#_using_keystorecallbackhandler_2)Using `KeyStoreCallbackHandler`
###### Using `KeyStoreCallbackHandler`
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including signing messages. For adding signatures, the handler uses the `keyStore` property. Additionally, you must set the `privateKeyPassword` property to unlock the private key used for signing. The following example uses a `KeyStoreCallbackHandler`:
......@@ -3000,11 +3000,11 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
#### [](#_decryption_and_encryption)7.1.4. Decryption and Encryption
#### 7.1.4. Decryption and Encryption
When encrypting, the message is transformed into a form that can be read only with the appropriate key. The message can be decrypted to reveal the original, readable message.
##### [](#_decryption)Decryption
##### Decryption
To decrypt incoming SOAP messages, the security policy file should contain a `RequireEncryption` element. This element can further carry a `EncryptionTarget` element that indicates which part of the message should be encrypted and a `SymmetricKey` to indicate that a shared secret instead of the regular private key should be used to decrypt the message. You can read a description of the other elements [here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951). The following example uses a `RequireEncryption` element:
......@@ -3016,7 +3016,7 @@ To decrypt incoming SOAP messages, the security policy file should contain a `Re
If an incoming message is not encrypted, the `XwsSecurityInterceptor` returns a SOAP ault to the sender. If it is present, it fires a `DecryptionKeyCallback` to the registered handlers. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
###### [](#_using_keystorecallbackhandler_3)Using `KeyStoreCallbackHandler`
###### Using `KeyStoreCallbackHandler`
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including decryption. For decryption, the handler uses the `keyStore` property. Additionally, you must set the `privateKeyPassword` property to unlock the private key used for decryption. For decryption based on symmetric keys, it uses the `symmetricStore`. The following example uses `KeyStoreCallbackHandler`:
......@@ -3034,7 +3034,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
##### [](#_encryption)Encryption
##### Encryption
To encrypt outgoing SOAP messages, the security policy file should contain an `Encrypt` element. This element can further carry a `EncryptionTarget` element that indicates which part of the message should be encrypted and a `SymmetricKey` to indicate that a shared secret instead of the regular public key should be used to encrypt the message. You can read a description of the other elements [here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951). The following example uses an `Encrypt` element:
......@@ -3046,7 +3046,7 @@ To encrypt outgoing SOAP messages, the security policy file should contain an `E
The `XwsSecurityInterceptor` fires an `EncryptionKeyCallback` to the registered handlers to retrieve the encryption information. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
###### [](#_using_keystorecallbackhandler_4)Using `KeyStoreCallbackHandler`
###### Using `KeyStoreCallbackHandler`
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including encryption. For encryption based on public keys, the handler uses the `trustStore` property. For encryption based on symmetric keys, it uses `symmetricStore`. The following example uses `KeyStoreCallbackHandler`:
......@@ -3063,7 +3063,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
#### [](#security-xws-exception-handling)7.1.5. Security Exception Handling
#### 7.1.5. Security Exception Handling
When a securement or validation action fails, the `XwsSecurityInterceptor` throws a `WsSecuritySecurementException` or `WsSecurityValidationException` respectively. These exceptions bypass the [standard exception handling mechanism](#server-endpoint-exception-resolver) but are handled by the interceptor itself.
......@@ -3074,7 +3074,7 @@ Similarly, `WsSecurityValidationException` exceptions are handled by the `handle
| |Both `handleSecurementException` and `handleValidationException` are protected methods, which you can override to change their default behavior.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#security-wss4j-security-interceptor)7.2. Using `Wss4jSecurityInterceptor`
### 7.2. Using `Wss4jSecurityInterceptor`
The `Wss4jSecurityInterceptor` is an `EndpointInterceptor` (see [Intercepting Requests — the `EndpointInterceptor` Interface](#server-endpoint-interceptor)) that is based on [Apache’s WSS4J](https://ws.apache.org/wss4j/).
......@@ -3088,7 +3088,7 @@ WSS4J implements the following standards:
This interceptor supports messages created by the `AxiomSoapMessageFactory` and the `SaajSoapMessageFactory`.
#### [](#_configuring_wss4jsecurityinterceptor)7.2.1. Configuring `Wss4jSecurityInterceptor`
#### 7.2.1. Configuring `Wss4jSecurityInterceptor`
WSS4J uses no external configuration file. The interceptor is entirely configured by properties. The validation and securement actions invoked by this interceptor are specified via `validationActions` and `securementActions` properties, respectively. Actions are passed as a space-separated strings. The following listing shows an example configuration:
......@@ -3124,13 +3124,13 @@ The following table shows the available securement actions:
The order of the actions is significant and is enforced by the interceptor. If its security actions were performed in a different order than the one specified by`validationActions`, the interceptor rejects an incoming SOAP message.
#### [](#_handling_digital_certificates)7.2.2. Handling Digital Certificates
#### 7.2.2. Handling Digital Certificates
For cryptographic operations that require interaction with a keystore or certificate handling (signature, encryption, and decryption operations), WSS4J requires an instance of`org.apache.ws.security.components.crypto.Crypto`.
`Crypto` instances can be obtained from WSS4J’s `CryptoFactory` or more conveniently with the Spring-WS`CryptoFactoryBean`.
##### [](#_cryptofactorybean)CryptoFactoryBean
##### CryptoFactoryBean
Spring-WS provides a convenient factory bean, `CryptoFactoryBean`, that constructs and configures `Crypto` instances through strongly typed properties (preferred) or through a `Properties` object.
......@@ -3145,17 +3145,17 @@ The following example configuration uses `CryptoFactoryBean`:
</bean>
```
#### [](#_authentication_2)7.2.3. Authentication
#### 7.2.3. Authentication
This section addresses how to do authentication with `Wss4jSecurityInterceptor`.
##### [](#_validating_username_token)Validating Username Token
##### Validating Username Token
Spring-WS provides a set of callback handlers to integrate with Spring Security. Additionally, a simple callback handler, `SimplePasswordValidationCallbackHandler`, is provided to configure users and passwords with an in-memory `Properties` object.
Callback handlers are configured through the `validationCallbackHandler` of the `Wss4jSecurityInterceptor` property.
###### [](#_using_simplepasswordvalidationcallbackhandler_2)Using `SimplePasswordValidationCallbackHandler`
###### Using `SimplePasswordValidationCallbackHandler`
`SimplePasswordValidationCallbackHandler` validates plain text and digest username tokens against an in-memory `Properties` object. You can configure it as follows:
......@@ -3170,7 +3170,7 @@ Callback handlers are configured through the `validationCallbackHandler` of the
</bean>
```
###### [](#_using_springsecuritypasswordvalidationcallbackhandler)Using `SpringSecurityPasswordValidationCallbackHandler`
###### Using `SpringSecurityPasswordValidationCallbackHandler`
The `SpringSecurityPasswordValidationCallbackHandler` validates plain text and digest passwords by using a Spring Security `UserDetailService` to operate. It uses this service to retrieve the the password (or a digest of the password) of the user specified in the token. The password (or a digest of the password) contained in this details object is then compared with the digest in the message. If they are equal, the user has successfully authenticated, and a `UsernamePasswordAuthenticationToken` is stored in the`SecurityContextHolder`. You can set the service by using the `userDetailsService`. Additionally, you can set a `userCache` property, to cache loaded user details, as follows:
......@@ -3185,7 +3185,7 @@ The `SpringSecurityPasswordValidationCallbackHandler` validates plain text and d
</beans>
```
##### [](#_adding_username_token)Adding Username Token
##### Adding Username Token
Adding a username token to an outgoing message is as simple as adding `UsernameToken` to the `securementActions` property of the `Wss4jSecurityInterceptor` and specifying `securementUsername` and`securementPassword`.
......@@ -3215,7 +3215,7 @@ The following example generates a username token with a plain text password, a `
</bean>
```
##### [](#_certificate_authentication)Certificate Authentication
##### Certificate Authentication
As certificate authentication is akin to digital signatures, WSS4J handles it as part of the signature validation and securement. Specifically, the `securementSignatureKeyIdentifier` property must be set to `DirectReference` in order to instruct WSS4J to generate a `BinarySecurityToken` element containing the X509 certificate and to include it in the outgoing message. The certificate’s name and password are passed through the `securementUsername` and `securementPassword` properties, respectively, as the following example shows:
......@@ -3252,11 +3252,11 @@ At the end of the validation, the interceptor automatically verifies the validit
For more detail, see to [Digital Signatures](#security-wss4j-digital-signatures).
#### [](#_security_timestamps)7.2.4. Security Timestamps
#### 7.2.4. Security Timestamps
This section describes the various timestamp options available in the `Wss4jSecurityInterceptor`.
##### [](#_validating_timestamps)Validating Timestamps
##### Validating Timestamps
To validate timestamps, add `Timestamp` to the `validationActions` property. You can override timestamp semantics specified by the initiator of the SOAP message by setting `timestampStrict` to `true` and specifying a server-side time-to-live in seconds (default: 300) by setting the `timeToLive` property. The interceptor always rejects already expired timestamps, whatever the value of `timeToLive` is.
......@@ -3270,7 +3270,7 @@ In the following example, the interceptor limits the timestamp validity window t
</bean>
```
##### [](#_adding_timestamps)Adding Timestamps
##### Adding Timestamps
Adding `Timestamp` to the `securementActions` property generates a timestamp header in outgoing messages. The `timestampPrecisionInMilliseconds` property specifies whether the precision of the generated timestamp is in milliseconds. The default value is `true`. The following listing adds a timestamp:
......@@ -3281,11 +3281,11 @@ Adding `Timestamp` to the `securementActions` property generates a timestamp hea
</bean>
```
#### [](#security-wss4j-digital-signatures)7.2.5. Digital Signatures
#### 7.2.5. Digital Signatures
This section describes the various signature options available in the `Wss4jSecurityInterceptor`.
##### [](#_verifying_signatures)Verifying Signatures
##### Verifying Signatures
To instruct the `Wss4jSecurityInterceptor`, `validationActions` must contain the `Signature` action. Additionally, the `validationSignatureCrypto` property must point to the keystore containing the public certificates of the initiator:
......@@ -3301,7 +3301,7 @@ To instruct the `Wss4jSecurityInterceptor`, `validationActions` must contain the
</bean>
```
##### [](#_signing_messages_2)Signing Messages
##### Signing Messages
Signing outgoing messages is enabled by adding the `Signature` action to the `securementActions`. The alias and the password of the private key to use are specified by the `securementUsername` and `securementPassword` properties, respectively. `securementSignatureCrypto` must point to the keystore that contains the private key:
......@@ -3336,7 +3336,7 @@ To specify an element without a namespace, use the string, `Null` (case sensitiv
If no other element in the request has a local name of `Body`, the SOAP namespace identifier can be empty (`{}`).
##### [](#_signature_confirmation)Signature Confirmation
##### Signature Confirmation
Signature confirmation is enabled by setting `enableSignatureConfirmation` to `true`. Note that the signature confirmation action spans over the request and the response. This implies that `secureResponse` and `validateRequest` must be set to `true` (which is the default value) even if there are no corresponding security actions. The following example sets the `enableSignatureConfirmation` property to `true`:
......@@ -3353,11 +3353,11 @@ Signature confirmation is enabled by setting `enableSignatureConfirmation` to `t
</bean>
```
#### [](#_decryption_and_encryption_2)7.2.6. Decryption and Encryption
#### 7.2.6. Decryption and Encryption
This section describes the various decryption and encryption options available in the `Wss4jSecurityInterceptor`.
##### [](#_decryption_2)Decryption
##### Decryption
Decryption of incoming SOAP messages requires that the `Encrypt` action be added to the `validationActions` property. The rest of the configuration depends on the key information that appears in the message. (This is because WSS4J needs only a Crypto for encypted keys, whereas embedded key name validation is delegated to a callback handler.)
......@@ -3400,7 +3400,7 @@ To support decryption of messages with an embedded key name ( `ds:KeyName` eleme
</bean>
```
##### [](#_encryption_2)Encryption
##### Encryption
Adding `Encrypt` to the `securementActions` enables encryption of outgoing messages. You can set the certificate’s alias to use for the encryption by setting the `securementEncryptionUser` property. The keystore where the certificate resides is accessed through the `securementEncryptionCrypto` property. As encryption relies on public certificates, no password needs to be passed. The following example uses the `securementEncryptionCrypto` property:
......@@ -3457,20 +3457,20 @@ Be aware that the element name, the namespace identifier, and the encryption mod
To specify an element without a namespace, use the value, `Null` (case sensitive), as the namespace name. If no list is specified, the handler encrypts the SOAP Body in `Content` mode by default.
#### [](#_security_exception_handling)7.2.7. Security Exception Handling
#### 7.2.7. Security Exception Handling
The exception handling of the `Wss4jSecurityInterceptor` is identical to that of the `XwsSecurityInterceptor`. See [Security Exception Handling](#security-xws-exception-handling) for more information.
# [](#resources)III. Other Resources
# III. Other Resources
In addition to this reference documentation, a number of other resources may help you learn how to use Spring Web Services. These additional, third-party resources are enumerated in this section.
## [](#_bibliography)Bibliography
## Bibliography
* []()[waldo-94] Jim Waldo, Ann Wollrath, and Sam Kendall. *A Note on Distributed Computing*. Springer Verlag. 1994
* [waldo-94] Jim Waldo, Ann Wollrath, and Sam Kendall. *A Note on Distributed Computing*. Springer Verlag. 1994
* []()[alpine] Steve Loughran & Edmund Smith. *Rethinking the Java SOAP Stack*. May 17, 2005. © 2005 IEEE Telephone Laboratories, Inc.
* [alpine] Steve Loughran & Edmund Smith. *Rethinking the Java SOAP Stack*. May 17, 2005. © 2005 IEEE Telephone Laboratories, Inc.
* []()[effective-enterprise-java] Ted Neward. Scott Meyers. *Effective Enterprise Java*. Addison-Wesley. 2004
* [effective-enterprise-java] Ted Neward. Scott Meyers. *Effective Enterprise Java*. Addison-Wesley. 2004
* []()[effective-xml] Elliotte Rusty Harold. Scott Meyers. *Effective XML*. Addison-Wesley. 2004
\ No newline at end of file
* [effective-xml] Elliotte Rusty Harold. Scott Meyers. *Effective XML*. Addison-Wesley. 2004
\ No newline at end of file
# Spring Web 服务参考文档
## [](#overview)序言
## 序言
在当前面向服务的体系结构时代,越来越多的人使用 Web 服务来连接以前未连接的系统。最初,Web 服务被认为是执行远程过程调用的另一种方式。然而,随着时间的推移,人们发现 RPC 和 Web 服务之间存在很大的差异。特别是当与其他平台的互操作性很重要时,通常更好的做法是发送封装的 XML 文档,其中包含处理请求所需的所有数据。从概念上讲,与消息队列相比,基于 XML 的 Web 服务比远程解决方案更好。总的来说,XML 应该被认为是数据的平台中立表示,即 SOA 的*通用语言*。在开发或使用 Web 服务时,重点应该放在这个 XML 上,而不是 Java 上。
Spring Web 服务专注于创建这些文档驱动的 Web 服务。 Spring Web 服务促进了契约优先的 SOAP 服务开发,允许通过使用操纵 XML 有效负载的多种方法之一来创建灵活的 Web 服务。 Spring-WS 提供了一个功能强大的[消息调度框架](#server)、一个与你现有的应用程序安全解决方案集成的[WS-Security](#security)解决方案,以及一个遵循熟悉的 Spring 模板模式的[客户端 API](#client)
# [](#_i_introduction)一.导言
# 一.导言
这是参考文献[是一个概述](#what-is-spring-ws)的第一部分 Spring Web 服务和底层概念。 Spring-WS 随后被介绍,并且[概念](#why-contract-first)契约优先 Web 服务开发的背后的[概念](#why-contract-first)被解释。
## [](#what-is-spring-ws)1。什么是 Spring Web 服务?
## 1.什么是 Spring Web 服务?
### [](#_introduction)1.1。导言
### 1.1.导言
Spring Web 服务( Spring-WS)是 Spring 社区的产品,并且专注于创建文档驱动的 Web 服务。 Spring Web 服务旨在促进契约优先的 SOAP 服务开发,允许通过使用操纵 XML 有效负载的多种方法之一来创建灵活的 Web 服务。该产品基于 Spring 本身,这意味着你可以使用 Spring 概念(例如依赖注入)作为 Web 服务的一个组成部分。
......@@ -32,35 +32,35 @@ Spring Web 服务( Spring-WS)是 Spring 社区的产品,并且专注于创
* [Apache license](#features-apache-license)
#### [](#features-powerful-mappings)1.1.1。强大的映射
#### 1.1.1.强大的映射
你可以将传入的 XML 请求分发到任何对象,这取决于消息有效负载、SOAP 动作报头或 XPath 表达式。
#### [](#features-xml-api-support)1.1.2。XML API 支持
#### 1.1.2.XML API 支持
传入的 XML 消息不仅可以通过标准的 JAXP API(如 DOM、SAX 和 STAX)来处理,还可以通过 JDOM、DOM4J、XOM 甚至编组技术来处理。
#### [](#features-flexible-xml-marshalling)1.1.3。灵活的 XML 编组
#### 1.1.3.灵活的 XML 编组
Spring Web 服务构建在 Spring 框架中的对象/XML 映射模块上,该模块支持 JAXB1 和 2、Castor、XMLBeans、JiBX 和 XStream。
#### [](#features-reusing-your-spring-expertise)1.1.4。重用你的 Spring 专长
#### 1.1.4.重用你的 Spring 专长
Spring-WS 对所有配置都使用 Spring 应用程序上下文,这应该有助于 Spring 开发人员快速获得最新信息。另外, Spring-WS 的体系结构类似于 Spring-MVC 的体系结构。
#### [](#features-support-for-ws-security)1.1.5。对 WS-Security 的支持
#### 1.1.5.对 WS-Security 的支持
WS-Security 允许你对 SOAP 消息进行签名、加密和解密,或者针对它们进行身份验证。
#### [](#features-integration-with-spring-security)1.1.6。与 Spring 安全性的集成
#### 1.1.6.与 Spring 安全性的集成
Spring Web 服务的 WS-Security 实现提供了与 Spring 安全性的集成。这意味着你也可以为你的 SOAP 服务使用你现有的 Spring 安全配置。
#### [](#features-apache-license)1.1.7。 Apache 许可证
#### 1.1.7. Apache 许可证
你可以放心地在项目中使用 Spring-WS。
### [](#_runtime_environment)1.2。运行时环境
### 1.2.运行时环境
Spring Web 服务需要一个标准的 Java8 运行时环境。 Spring-WS 是基于 Spring Framework4.0.9 构建的,但支持更高的版本。
......@@ -78,7 +78,7 @@ Spring-WS 由许多模块组成,这些模块在本节的其余部分中进行
![spring deps](spring-deps.png)
### [](#_supported_standards)1.3。支持的标准
### 1.3.支持的标准
Spring Web 服务支持以下标准:
......@@ -92,7 +92,7 @@ Spring Web 服务支持以下标准:
* SOAP 消息安全 1.1,用户名令牌配置文件 1.1,X.509 证书令牌配置文件 1.1,SAML 令牌配置文件 1.1,Kerberos 令牌配置文件 1.1,基本安全配置文件 1.1
## [](#why-contract-first)2。为什么要先签约?
## 2.为什么要先签约?
在创建 Web 服务时,有两种开发风格:Contract-last 和 Contract-first。当你使用契约-最后一种方法时,首先从 Java 代码开始,然后让 Web 服务契约(在 WSDL 中——参见侧边栏)从中生成。当使用 Contract-First 时,你可以从 WSDL Contract 开始,并使用 Java 来实现该 Contract。
......@@ -102,14 +102,14 @@ WSDL 代表 Web 服务描述语言。WSDL 文件是描述 Web 服务的 XML 文
Spring-WS 只支持契约优先的开发风格,本节解释了原因。
### [](#_objectxml_impedance_mismatch)2.1。对象/XML 阻抗不匹配
### 2.1.对象/XML 阻抗不匹配
与 ORM 领域类似,在 ORM 领域中,我们有[对象/关系阻抗不匹配](https://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch),将 Java 对象转换为 XML 也有类似的问题。乍一看,O/X 映射问题似乎很简单:为每个 Java 对象创建一个 XML 元素,将所有 Java 属性和字段转换成子元素或属性。然而,事情并不像表面上看起来那么简单,因为层次化语言(例如 XML(尤其是 XSD))与 Java 的图形模型之间存在根本的区别。
| |这一部分的大部分内容都受到了[[alpine]和[[effective-Enterprise-java]](#effective-Enterprise-java)的启发。|
|---|----------------------------------------------------------------------------------------------------------------------------------------|
#### [](#_xsd_extensions)2.1.1。XSD 扩展
#### 2.1.1.XSD 扩展
在 Java 中,改变类的行为的唯一方法是对其进行子类分类,以便将新的行为添加到该子类中。在 XSD 中,你可以通过限制数据类型来扩展数据类型——也就是说,限制元素和属性的有效值。例如,考虑以下示例:
......@@ -123,7 +123,7 @@ Spring-WS 只支持契约优先的开发风格,本节解释了原因。
这种类型通过正则表达式来限制 XSD 字符串,只允许三个大写字母。如果将此类型转换为 Java,则最终得到一个普通的`java.lang.String`。正则表达式在转换过程中丢失,因为 Java 不允许这些类型的扩展。
#### [](#_unportable_types)2.1.2。不可移植类型
#### 2.1.2.不可移植类型
Web 服务最重要的目标之一是可互操作:支持多个平台,如 Java、.NET、Python 和其他平台。因为所有这些语言都有不同的类库,所以你必须使用一些常见的跨语言格式来在它们之间进行通信。这种格式是 XML,所有这些语言都支持这种格式。
......@@ -157,7 +157,7 @@ public Map getFlights() {
此契约定义了一个请求,该请求接受`date`,这是一个表示年、月和日的 XSD 数据类型。如果我们从 Java 调用这个服务,我们可能使用`java.util.Date``java.util.Calendar`。然而,这两个类实际上都描述了时间,而不是日期。因此,我们最终实际上发送了代表 2007 年 4 月 4 日午夜的数据(`2007-04-04T00:00:00`),这与`2007-04-04`不同。
#### [](#_cyclic_graphs)2.1.3。循环图
#### 2.1.3.循环图
假设我们有如下的类结构:
......@@ -215,7 +215,7 @@ public class Passenger {
这些只是处理 O/X 映射时的一些问题。在编写 Web 服务时,尊重这些问题是很重要的。尊重它们的最好方法是完全关注 XML,同时使用 Java 作为一种实现语言。这就是契约优先的意义所在。
### [](#_contract_first_versus_contract_last)2.2。合同优先与合同优先
### 2.2.合同优先与合同优先
除了上一节中提到的对象/XML 映射问题外,还有其他原因使我们更喜欢契约优先的开发风格。
......@@ -227,7 +227,7 @@ public class Passenger {
* [Versioning](#contract-first-versioning)
#### [](#contract-first-fragility)2.2.1。脆弱性
#### 2.2.1.脆弱性
如前所述,Contract-Last 开发风格导致你的 Web 服务契约(WSDL 和你的 XSD)是从你的 Java 契约(通常是一个接口)生成的。如果你使用这种方法,你不能保证合同随着时间的推移而保持不变。每次更改 Java 契约并重新部署它时,可能都会对 Web 服务契约进行后续更改。
......@@ -237,13 +237,13 @@ public class Passenger {
要使合同有用,它必须尽可能长时间地保持不变。如果合同变更,你必须与服务的所有用户联系,并指示他们获得新版本的合同。
#### [](#contract-first-performance)2.2.2。表现
#### 2.2.2.表现
当一个 Java 对象被自动转换为 XML 时,就无法确定哪些内容是通过连接发送的。一个对象可能引用另一个对象,后者引用另一个对象,依此类推。最后,虚拟机中堆上的一半对象可能会转换为 XML,这会导致响应时间变慢。
在使用 Contract-First 时,你将显式地描述将哪些 XML 发送到哪里,从而确保它正是你想要的。
#### [](#contract-first-reusability)2.2.3。可重用性
#### 2.2.3.可重用性
在一个单独的文件中定义模式,可以让你在不同的场景中重用该文件。考虑一个名为`airline.xsd`的文件中`AirportCode`的定义:
......@@ -257,13 +257,13 @@ public class Passenger {
通过使用`import`语句,可以在其他模式甚至 WSDL 文件中重用此定义。
#### [](#contract-first-versioning)2.2.4。版本化
#### 2.2.4.版本化
尽管合同必须尽可能长时间保持不变,但有时确实需要更改。在 Java 中,这通常会产生一个新的 Java 接口,例如`AirlineService2`,以及该接口的(新的)实现。当然,必须保留旧的服务,因为可能有一些客户尚未迁移。
如果使用 Contract-First,我们可以在 Contract 和实现之间有一个更松散的耦合。这样的松散耦合使我们能够在一个类中实现契约的两个版本。例如,我们可以使用 XSLT 样式表将任何“旧式”消息转换为“新式”消息。
## [](#tutorial)3。书面合同优先的 Web 服务
## 3.书面合同优先的 Web 服务
本教程向你展示了如何编写[契约优先的 Web 服务](#why-contract-first)——也就是说,如何开发首先从 XML 模式或 WSDL 契约开始,然后是 Java 代码的 Web 服务。 Spring-WS 专注于这种开发风格,本教程应该帮助你开始学习。请注意,本教程的第一部分几乎不包含 Spring-WS 特定的信息。它主要是关于 XML、XSD 和 WSDL 的。[第二部分](#tutorial-creating-project)着重于用 Spring-WS 实现这个契约。
......@@ -271,11 +271,11 @@ public class Passenger {
在本教程中,我们定义了一个由人力资源部门创建的 Web 服务。客户可以向这项服务发送假期申请表格来预订假期。
### [](#_messages)3.1。信息
### 3.1.信息
在这一节中,我们将重点关注发送到 Web 服务和从 Web 服务发送的实际 XML 消息。我们首先要确定这些信息是什么样子的。
#### [](#_holiday)3.1.1。假日
#### 3.1.1.假日
在该场景中,我们必须处理假期请求,因此确定 XML 中的假期是什么样子是有意义的:
......@@ -288,7 +288,7 @@ public class Passenger {
假日由开始日期和结束日期组成。我们还决定对日期使用标准的[ISO 8601](https://www.cl.cam.ac.uk/~mgk25/iso-time.html)日期格式,因为这节省了大量的解析麻烦。我们还向元素添加了一个命名空间,以确保我们的元素可以在其他 XML 文档中使用。
#### [](#_employee)3.1.2。雇员
#### 3.1.2.雇员
在这个场景中,还有一个员工的概念。以下是它在 XML 中的样子:
......@@ -302,7 +302,7 @@ public class Passenger {
我们使用了与以前相同的名称空间。如果`<Employee/>`元素可以在其他场景中使用,那么使用不同的名称空间可能是有意义的,例如`[http://example.com/employees/schemas](http://example.com/employees/schemas)`
#### [](#_holidayrequest)3.1.3。度假请求
#### 3.1.3.度假请求
`holiday`元素和`employee`元素都可以放在`<HolidayRequest/>`中:
......@@ -322,7 +322,7 @@ public class Passenger {
这两个元素的顺序并不重要:`<Employee/>`可能是第一个元素。重要的是,所有的数据都在那里。事实上,数据是唯一重要的东西:我们采用数据驱动的方法。
### [](#tutorial.xsd)3.2。数据契约
### 3.2.数据契约
既然我们已经看到了一些可以使用的 XML 数据的示例,那么将其形式化为一个模式是有意义的。这个数据契约定义了我们接受的消息格式。为 XML 定义这样的契约有四种不同的方式:
......@@ -459,7 +459,7 @@ DTD 的名称空间支持有限,因此它们不适合于 Web 服务。RELAXNG
我们将此文件存储为`hr.xsd`
### [](#tutorial-service-contract)3.3。服务合同
### 3.3.服务合同
服务契约通常表示为[WSDL](https://www.w3.org/TR/wsdl)文件。请注意,在 Spring-WS 中,不需要手工编写 WSDL。基于 XSD 和一些约定, Spring-WS 可以为你创建 WSDL,如在标题为[实现端点](#tutorial-implementing-endpoint)的部分中所解释的那样。本节的其余部分展示了如何手工编写 WSDL。你可能希望跳到[下一节](#tutorial-creating-project)
......@@ -551,7 +551,7 @@ DTD 的名称空间支持有限,因此它们不适合于 Web 服务。RELAXNG
前面的清单显示了最终的 WSDL。在下一节中,我们将描述如何实现生成的模式和 WSDL。
### [](#tutorial-creating-project)3.4。创建项目
### 3.4.创建项目
在本节中,我们使用[Maven](https://maven.apache.org/)为我们创建初始项目结构。这样做并不是必需的,但大大减少了我们为设置 HolidayService 而必须编写的代码量。
......@@ -596,11 +596,11 @@ mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
创建了项目结构之后,就可以将上一节中的模式和 WSDL 放入`'WEB-INF/'`文件夹中。
### [](#tutorial-implementing-endpoint)3.5。实现端点
### 3.5.实现端点
在 Spring-WS 中,实现端点来处理传入的 XML 消息。端点通常是通过使用`@Endpoint`注释对类进行注释来创建的。在这个端点类中,你可以创建一个或多个处理传入请求的方法。方法签名可以非常灵活。你可以包括与传入的 XML 消息相关的几乎任何类型的参数类型,正如我们在本章后面所解释的那样。
#### [](#_handling_the_xml_message)3.5.1。处理 XML 消息
#### 3.5.1.处理 XML 消息
在这个示例应用程序中,我们使用[JDom 2](http://www.jdom.org/)来处理 XML 消息。我们还使用[XPath](https://www.w3.org/TR/xpath20/),因为它允许我们选择 XML JDOM 树的特定部分,而不需要严格的模式一致性。
......@@ -724,7 +724,7 @@ public class HolidayEndpoint {
</beans>
```
#### [](#_routing_the_message_to_the_endpoint)3.5.2。将消息路由到端点
#### 3.5.2.将消息路由到端点
作为编写端点的一部分,我们还使用`@PayloadRoot`注释来指示哪种消息可以由`handleHolidayRequest`方法处理。在 Spring-WS 中,这个过程是`EndpointMapping`的职责。在这里,我们使用`PayloadRootAnnotationMethodEndpointMapping`基于内容路由消息。下面的清单显示了我们之前使用的注释:
......@@ -736,7 +736,7 @@ public class HolidayEndpoint {
还有其他将端点映射到 XML 消息的方法,这在[下一章](#common)中进行了描述。
#### [](#_providing_the_service_and_stub_implementation)3.5.3。提供服务和存根实现
#### 3.5.3.提供服务和存根实现
现在我们有了端点,我们需要`HumanResourceService`及其实现,供`HolidayEndpoint`使用。下面的清单显示了`HumanResourceService`接口:
......@@ -770,7 +770,7 @@ public class StubHumanResourceService implements HumanResourceService {
|**1**|`StubHumanResourceService`注释为`@Service`。这将类标记为一个业务外观,这使得它成为`@Autowired`中注入的候选项。|
|-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#tutorial-publishing-wsdl)3.6。发布 WSDL
### 3.6.发布 WSDL
最后,我们需要发布 WSDL。正如[服务合同](#tutorial-service-contract)中所述,我们不需要自己编写 WSDL。 Spring-WS 可以基于一些约定生成一个。以下是我们对这一代的定义:
......@@ -803,19 +803,19 @@ public class StubHumanResourceService implements HumanResourceService {
本教程到此结束。教程代码可以在 Spring-WS 的完整发行版中找到。如果你希望继续,请查看作为发行版一部分的 echo 示例应用程序。在此之后,看一下航空公司示例,它有点复杂,因为它使用了 JAXB、WS-Security、 Hibernate 和事务性服务层。最后,你可以阅读参考文档的其余部分。
# [](#_ii_reference)ii。参考文献
# ii。参考文献
参考文档的这一部分详细介绍了构成 Spring Web 服务的各个组件。其中包括[a chapter](#common),讨论了客户端和服务器端 WS 共有的部分,专门讨论[编写服务器端 Web 服务](#server)的细节的一章,关于在[客户端](#client)上使用 Web 服务的一章,以及关于使用[WS-Security](#security)的一章。
## [](#common)4。共享组件
## 4.共享组件
本章将探讨在客户端和服务器端之间共享的组件 Spring-WS 开发。这些接口和类代表了 Spring-WS 的构建块,因此你需要理解它们的功能,即使你不直接使用它们。
### [](#web-service-messages)4.1。Web 服务消息
### 4.1.Web 服务消息
本节描述了 Spring-WS 使用的消息和消息工厂。
#### [](#web-service-message)4.1.1。`WebServiceMessage`
#### 4.1.1.`WebServiceMessage`
Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示与协议无关的 XML 消息。接口包含以`javax.xml.transform.Source``javax.xml.transform.Result`的形式提供对消息有效负载的访问的方法。`Source``Result`是标记接口,表示对 XML 输入和输出的抽象。具体的实现封装了各种 XML 表示,如下表所示:
......@@ -830,15 +830,15 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
除了读取和写入有效负载外,Web 服务消息还可以将自身写入输出流。
#### [](#soap-message)4.1.2。`SoapMessage`
#### 4.1.2.`SoapMessage`
`SoapMessage``WebServiceMessage`的一个子类。它包含特定于 SOAP 的方法,例如获取 SOAP 头、SOAP 错误等等。通常,你的代码不应该依赖于`SoapMessage`,因为可以通过在`WebServiceMessage`中使用`getPayloadSource()``getPayloadResult()`来获得 SOAP 主体的内容(消息的有效负载)。只有在需要执行特定于 SOAP 的操作(例如添加标头、获取附件等)时,才需要将`WebServiceMessage`强制转换为`SoapMessage`
#### [](#message-factories)4.1.3。消息工厂
#### 4.1.3.消息工厂
具体的消息实现是由`WebServiceMessageFactory`创建的。这个工厂可以创建一个空消息或从输入流中读取消息。`WebServiceMessageFactory`有两个具体的实现方式。一种是基于 SAAJ 的,SAAJ 是一种带有 Java 附件 API 的 SOAP。另一种是基于 Axis2 的公理(Axis Object Model)。
##### [](#_saajsoapmessagefactory)`SaajSoapMessageFactory`
##### `SaajSoapMessageFactory`
`SaajSoapMessageFactory`使用 SOAP with Attachments API for Java 来创建`SoapMessage`实现。SAAJ 是 J2EE1.4 的一部分,因此大多数现代应用程序服务器都应该支持它。以下是常见应用程序服务器提供的 SAAJ 版本的概述:
......@@ -848,9 +848,9 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
|BEA WebLogic9|1.1/1.2<sup>1</sup>|
|IBMWebSphere6| 1.2 |
|Sun Glassfish 鱼 1| 1.3 |
|<sup>1</sup>WebLogic9 在 SAAJ1.2 实现中有一个已知的错误:它实现了所有的 1.2 接口,但在调用时抛出一个`UnsupportedOperationException`。 Spring Web 服务有一个解决方法:当在 WebLogic9 上操作时,它使用 SAAJ1.1| |
|<sup>1</sup>WebLogic9 在 SAAJ1.2 实现中有一个已知的错误:它实现了所有的 1.2 接口,但在调用时抛出一个`UnsupportedOperationException`。 Spring Web 服务有一个解决方法:当在 WebLogic9 上操作时,它使用 SAAJ1.1.| |
此外,Java SE6 还包括 SAAJ1.3你可以按以下方式连接`SaajSoapMessageFactory`:
此外,Java SE6 还包括 SAAJ1.3.你可以按以下方式连接`SaajSoapMessageFactory`:
```
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
......@@ -859,7 +859,7 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
| |SAAJ 是基于 DOM 的文档对象模型。这意味着所有 SOAP 消息都存储在内存中。对于较大的 SOAP 消息,这可能不是性能。在这种情况下,`AxiomSoapMessageFactory`可能更适用。|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
##### [](#_axiomsoapmessagefactory)`AxiomSoapMessageFactory`
##### `AxiomSoapMessageFactory`
`AxiomSoapMessageFactory`使用 Axis2 对象模型来创建`SoapMessage`实现。AXIOM 是基于 STAX 的,STAX 是 XML 的流媒体 API。STAX 为读取 XML 消息提供了一种基于拉的机制,对于较大的消息,这种机制可能更有效。
......@@ -879,7 +879,7 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
有关完整流的更多信息,请参见`StreamingWebServiceMessage``StreamingPayload`的类级 Javadoc。
##### [](#soap_11_or_12)SOAP1.1 或 1.2
##### SOAP1.1 或 1.2
`SaajSoapMessageFactory``AxiomSoapMessageFactory`都具有`soapVersion`属性,可以在其中注入一个`SoapVersion`常数。默认情况下,该版本是 1.1,但你可以将其设置为 1.2:
......@@ -903,16 +903,16 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
在前面的示例中,我们定义了只接受 SOAP1.2 消息的`SaajSoapMessageFactory`
| |尽管两个版本的 SOAP 在格式上非常相似,但 1.2 版本并不向后兼容 1.1,因为它使用了不同的 XML 命名空间。SOAP1.1 和 1.2 之间的其他主要区别包括错误的不同结构,以及`SOAPAction`HTTP 头实际上已被弃用,尽管它们仍然有效。<br/><br/>使用 SOAP 版本号(或一般的 WS-\* 规范版本号)需要注意的一件重要事情是,规范的最新版本通常不是最流行的版本。对于 SOAP,这意味着(目前)使用的最佳版本是 1.1版本 1.2 可能会在未来变得更受欢迎,但 1.1 是目前最安全的选择。|
| |尽管两个版本的 SOAP 在格式上非常相似,但 1.2 版本并不向后兼容 1.1,因为它使用了不同的 XML 命名空间。SOAP1.1 和 1.2 之间的其他主要区别包括错误的不同结构,以及`SOAPAction`HTTP 头实际上已被弃用,尽管它们仍然有效。<br/><br/>使用 SOAP 版本号(或一般的 WS-\* 规范版本号)需要注意的一件重要事情是,规范的最新版本通常不是最流行的版本。对于 SOAP,这意味着(目前)使用的最佳版本是 1.1.版本 1.2 可能会在未来变得更受欢迎,但 1.1 是目前最安全的选择。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#message-context)4.1.4。`MessageContext`
#### 4.1.4.`MessageContext`
通常,消息是成对出现的:请求和响应。在客户端创建一个请求,该请求通过一些传输发送到服务器端,在服务器端生成响应。这个响应被发送回客户机,在那里进行读取。
在 Spring Web 服务中,这样的会话包含在`MessageContext`中,其具有获取请求和响应消息的属性。在客户端,消息上下文由[`WebServiceTemplate`](#client-web-service-template)创建。在服务器端,消息上下文是从特定于传输的输入流中读取的。例如,在 HTTP 中,从`HttpServletRequest`读取,然后将响应写回`HttpServletResponse`
### [](#transport-context)4.2。`TransportContext`
### 4.2.`TransportContext`
SOAP 协议的一个关键属性是它试图与传输无关。这就是为什么 Spring-WS 不支持通过 HTTP 请求 URL 而是通过消息内容将消息映射到端点的原因。
......@@ -925,7 +925,7 @@ HttpServletRequest request = connection.getHttpServletRequest();
String ipAddress = request.getRemoteAddr();
```
### [](#xpath)4.3。使用 XPath 处理 XML
### 4.3.使用 XPath 处理 XML
处理 XML 的最佳方法之一是使用 XPath。引用[[effective-xml]],项目 35:
......@@ -935,7 +935,7 @@ String ipAddress = request.getRemoteAddr();
Spring Web 服务有两种在应用程序中使用 XPath 的方式:更快的`XPathExpression`或更灵活的`XPathTemplate`
#### [](#xpath-expression)4.3.1。`XPathExpression`
#### 4.3.1.`XPathExpression`
`XPathExpression`是对已编译的 XPath 表达式的抽象,例如 Java5`javax.xml.xpath.XPathExpression`接口或 Jaxen`XPath`类。要在应用程序上下文中构造表达式,可以使用`XPathExpressionFactoryBean`。下面的示例使用了这个工厂 Bean:
......@@ -1007,7 +1007,7 @@ public class MyXPathClass {
与 Spring JDBC 的`RowMapper`中的映射行类似,每个结果节点都通过使用匿名内部类进行映射。在这种情况下,我们创建一个`Contact`对象,稍后将使用它。
#### [](#xpath-template)4.3.2。`XPathTemplate`
#### 4.3.2.`XPathTemplate`
`XPathExpression`只允许对单个预编译表达式求值。一个更灵活但更慢的替代方案是`XpathTemplate`。该类遵循通篇 Spring 中使用的公共模板模式(`JdbcTemplate``JmsTemplate`,以及其他)。下面的清单展示了一个示例:
......@@ -1026,7 +1026,7 @@ public class MyXPathClass {
}
```
### [](#logging)4.4。消息日志记录和跟踪
### 4.4.消息日志记录和跟踪
在开发或调试 Web 服务时,在消息到达或发送之前查看消息的内容可能非常有用。 Spring Web 服务通过标准的 Commons 日志记录接口提供了这种功能。
......@@ -1060,7 +1060,7 @@ DEBUG [server.MessageTracing.sent] Sent response [SaajSoapMessage {http://exampl
DEBUG [client.MessageTracing.received] Received response [SaajSoapMessage {http://example.com}response] ...
```
## [](#server)5。使用 Spring-WS 创建 Web 服务
## 5.使用 Spring-WS 创建 Web 服务
Spring-WS 的服务器端支持是围绕`MessageDispatcher`设计的,该支持将传入消息分派到端点,具有可配置的端点映射、响应生成和端点拦截。端点通常使用`@Endpoint`注释并具有一个或多个处理方法。这些方法通过检查消息的某些部分(通常是有效负载)并创建某种响应来处理传入的 XML 请求消息。你可以使用另一个注释(通常是`@PayloadRoot`)对方法进行注释,以指示它可以处理哪种类型的消息。
......@@ -1074,7 +1074,7 @@ Spring-WS 的 XML 处理非常灵活。端点可以从 Spring-WS 支持的大量
* 编组技术(JAXB、Castor、XMLBeans、JiBX 或 XStream):将 XML 转换为对象,反之亦然
### [](#_the_messagedispatcher)5.1。the`MessageDispatcher`
### 5.1.the`MessageDispatcher`
Spring-WS 的服务器端是围绕一个中心类设计的,该中心类将传入的 XML 消息分派到端点。 Spring-WS 的`MessageDispatcher`非常灵活,允许你使用任何类型的类作为端点,只要它可以在 Spring IOC 容器中进行配置。在某种程度上,消息分配器类似于 Spring 的`DispatcherServlet`,即 Spring Web MVC 中使用的“前置控制器”。
......@@ -1096,11 +1096,11 @@ Spring-WS 的服务器端是围绕一个中心类设计的,该中心类将传
消息调度器对[消息上下文](#message-context)进行操作,而不是对特定于传输的输入流和输出流进行操作。因此,传输特定的请求需要读入`MessageContext`。对于 HTTP,这是用`WebServiceMessageReceiverHandlerAdapter`(这是 Spring web`HandlerInterceptor`)完成的,以便`MessageDispatcher`可以连接到标准`DispatcherServlet`中。然而,还有一种更方便的方法可以做到这一点,它显示在[`MessageDispatcherServlet`](#message-dispatcher- Servlet)中。
### [](#_transports)5.2。运输
### 5.2.运输
Spring Web 服务支持多个传输协议。最常见的是 HTTP 传输,为此提供了自定义 Servlet,但你也可以通过 JMS 甚至电子邮件发送消息。
#### [](#message-dispatcher-servlet)5.2.1。`MessageDispatcherServlet`
#### 5.2.1.`MessageDispatcherServlet`
`MessageDispatcherServlet`是一个标准`Servlet`,它方便地从标准 Spring web`DispatcherServlet`扩展并包装一个`MessageDispatcher`。因此,它将这些属性合并为一个。作为`MessageDispatcher`,它遵循上一节中描述的相同的请求处理流程。作为 Servlet,在 Web 应用程序的`MessageDispatcherServlet`中配置了`web.xml`。要处理`MessageDispatcherServlet`的请求必须通过同一个`web.xml`文件中的 URL 映射来映射。这是标准的 Java EE Servlet 配置。下面的示例显示了这样的`MessageDispatcherServlet`声明和映射:
......@@ -1144,7 +1144,7 @@ public class MyServletInitializer
在前面的示例中,我们告诉 Spring 端点 Bean 定义可以在`MyEndpointConfig`类中找到(这是`@Configuration`类)。 Bean 其他定义(通常是服务、存储库等)可以在`MyRootConfig`类中找到。默认情况下,`AbstractAnnotationConfigMessageDispatcherServletInitializer`将 Servlet 映射到两个模式:`/services``*.wsdl`,尽管你可以通过重写`getServletMappings()`方法对此进行更改。有关`MessageDispatcherServlet`的编程配置的更多详细信息,请参阅[`AbstractMessageDispatcherServletInitializer`](https://DOCS. Spring.io/ Spring-ws/DOCS/current/org/springframework/ws/transport/http/support/AbstractMessageDispatcherServletInitializer.html)和[<<gtr="530"/>](https://DOCS. Spring..io//// Spring-Messessframews/currumblessframews/curractork/sprintionframews/support/initializer.html)
##### [](#server-automatic-wsdl-exposure)自动 WSDL 曝光
##### 自动 WSDL 曝光
`MessageDispatcherServlet`自动检测在其 Spring 容器中定义的任何`WsdlDefinition`bean。所有检测到的`WsdlDefinition`bean 也都通过`WsdlDefinitionHandlerAdapter`公开。这是一种方便的方式,可以通过定义一些 bean 向客户机公开你的 WSDL。
......@@ -1237,7 +1237,7 @@ public DefaultWsdl11Definition orders() {
因此,你应该仅在项目的开发阶段使用`<dynamic-wsdl>`。我们建议使用你的浏览器下载生成的 WSDL,将其存储在项目中,并用`<static-wsdl>`公开它。这是确保 WSDL 不会随时间变化的唯一方法。
#### [](#_wiring_up_spring_ws_in_a_dispatcherservlet)5.2.2。在`DispatcherServlet`中连接 Spring-WS
#### 5.2.2.在`DispatcherServlet`中连接 Spring-WS
作为`MessageDispatcherServlet`的替代方案,你可以在标准 Spring-Web MVC`DispatcherServlet`中连接`MessageDispatcher`。默认情况下,`DispatcherServlet`只能委托给`Controllers`,但是我们可以通过在 Servlet 的 Web 应用程序上下文中添加`WebServiceMessageReceiverHandlerAdapter`来指示它委托给`MessageDispatcher`:
......@@ -1290,7 +1290,7 @@ public DefaultWsdl11Definition orders() {
</beans>
```
#### [](#_jms_transport)5.2.3。JMS 运输
#### 5.2.3.JMS 运输
Spring Web 服务通过在 Spring 框架中提供的 JMS 功能支持服务器端 JMS 处理。 Spring Web 服务提供`WebServiceMessageListener`以插入到`MessageListenerContainer`中。此消息侦听器需要`WebServiceMessageFactory``MessageDispatcher`才能操作。下面的配置示例展示了这一点:
......@@ -1327,7 +1327,7 @@ Spring Web 服务通过在 Spring 框架中提供的 JMS 功能支持服务器
</beans>
```
#### [](#_email_transport)5.2.4。电子邮件传输
#### 5.2.4.电子邮件传输
Spring 除了 HTTP 和 JMS,Web 服务还提供服务器端电子邮件处理。这个功能是通过`MailMessageReceiver`类提供的。该类监视 POP3 或 IMAP 文件夹,将电子邮件转换为`WebServiceMessage`,并使用 SMTP 发送任何响应。你可以通过`storeUri`配置主机名,该文件夹指示要监视请求的邮件文件夹(通常是 POP3 或 IMAP 文件夹),以及`transportUri`,该文件夹指示用于发送响应的服务器(通常是 SMTP 服务器)。
......@@ -1368,7 +1368,7 @@ Spring 除了 HTTP 和 JMS,Web 服务还提供服务器端电子邮件处理
</beans>
```
#### [](#_embedded_http_server_transport)5.2.5。嵌入式 HTTP 服务器传输
#### 5.2.5.嵌入式 HTTP 服务器传输
Spring Web 服务提供了基于 Sun 的 JRE1.6的传输。嵌入式 HTTP 服务器是一个独立的服务器,配置起来很简单。它提供了一种比传统 Servlet 容器更轻的替代品。
......@@ -1415,7 +1415,7 @@ Spring Web 服务提供了`HttpHandler`接口的两种实现方式:[`WsdlDefin
有关`SimpleHttpServerFactoryBean`的更多信息,请参见[Javadoc](http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/remoting/support/SimpleHttpServerFactoryBean.html)
#### [](#_xmpp_transport)5.2.6。XMPP 运输
#### 5.2.6.XMPP 运输
Spring Web 服务 2.0 引入了对 XMPP 的支持,也称为 Jabber。该支持基于[Smack](https://www.igniterealtime.org/projects/smack/index.jsp)库。
......@@ -1454,11 +1454,11 @@ Spring 用于 XMPP 的 Web 服务支持非常类似于其它传输:有一个
</beans>
```
#### [](#_mtom)5.2.7。姆托姆
#### 5.2.7.姆托姆
[MTOM](https://en.wikipedia.org/wiki/Message_Transmission_Optimization_Mechanism)是用于向 Web 服务发送和从 Web 服务发送二进制数据的机制。你可以通过[MTOM 样本](https://github.com/spring-projects/spring-ws-samples/tree/main/mtom)查看如何使用 Spring WS 实现这一点。
### [](#server-endpoints)5.3。端点
### 5.3.端点
端点是 Spring-WS 服务器端支持的核心概念。端点提供对应用程序行为的访问,该行为通常由业务服务接口定义。端点解释 XML 请求消息,并使用该输入(通常)调用业务服务上的方法。该服务调用的结果表示为响应消息。 Spring-WS 具有各种各样的端点,并且使用各种方式来处理 XML 消息并创建响应。
......@@ -1570,7 +1570,7 @@ public class MyConfiguration extends WsConfigurerAdapter {
Note that all abstract base classes provided in Spring-WS are thread safe, unless otherwise indicated in the class-level Javadoc.
```
#### [](#server-atEndpoint-methods)5.3.1。`@Endpoint`处理方法
#### 5.3.1.`@Endpoint`处理方法
要使端点实际处理传入的 XML 消息,它需要有一个或多个处理方法。处理方法可以使用范围很广的参数和返回类型。但是,它们通常有一个包含消息有效负载的参数,并且它们返回响应消息的有效负载(如果有的话)。本节将讨论支持哪些参数和返回类型。
......@@ -1588,7 +1588,7 @@ public void order(@RequestPayload Element orderElement) {
`order`方法将`Element`(注释为`@RequestPayload`)作为参数。这意味着消息的有效负载将作为 DOM 元素在此方法上传递。该方法具有`void`返回类型,表示未发送任何响应消息。
##### [](#_handling_method_parameters)处理方法参数
##### 处理方法参数
处理方法通常具有一个或多个参数,这些参数引用传入 XML 消息的各个部分。最常见的情况是,处理方法只有一个参数,该参数映射到消息的有效负载,但它也可以映射到请求消息的其他部分,例如 SOAP 头。本节描述了可以在处理方法签名中使用的参数。
......@@ -1630,7 +1630,7 @@ public void handle(@RequestPayload MyJaxb2Object requestObject, @RequestPayload
正如你所看到的,在定义如何处理方法签名时,有很多可能性。你甚至可以扩展此机制以支持你自己的参数类型。参见[`DefaultMethodEndpointAdapter`](https://DOCS. Spring.io/ Spring-ws/DOCS/current/api/org/springframework/ws/server/endpoint/adapter/defaultMethodPointadapter.html)和[<gtr="736"/>](<gtr://DOCS. Spring.io/ Spring-ws/DOCS/current/api/api/org/org/apframews/ws/server/endpoint/endpoint/dargumentver.html/metter/method/dapter.html)的 javadoc,
###### [](#server-xpath-param)`@XPathParam`
###### `@XPathParam`
一个参数类型需要一些额外的解释:`@XPathParam`。这里的想法是,你使用 XPath 表达式注释一个或多个方法参数,并且每个这样的注释参数都绑定到表达式的求值。下面的示例展示了如何做到这一点:
......@@ -1679,7 +1679,7 @@ public class AnnotationOrderEndpoint {
除了这个列表之外,你还可以使用可以从`String`转换为 Spring [转换服务](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#core-convert-ConversionService-API)的任何类型。
##### [](#_handling_method_return_types)处理方法返回类型
##### 处理方法返回类型
要发送响应消息,处理需要指定一个返回类型。如果不需要响应消息,则该方法可以声明`void`返回类型。通常,返回类型用于创建响应消息的有效负载。但是,你也可以映射到响应消息的其他部分。本节描述了可以在处理方法签名中使用的返回类型。
......@@ -1700,7 +1700,7 @@ public class AnnotationOrderEndpoint {
当涉及到定义处理方法签名时,有很多可能性。甚至可以扩展此机制以支持你自己的参数类型。参见[`DefaultMethodEndpointAdapter`](https://DOCS. Spring.io/ Spring-ws/DOCS/current/api/org/springframework/ws/server/endpoint/adapter/defaultMethodPointAdapter.html)和[<`MethodReturnValueHandler`](https://DOCS. Spring.io/ Spring-ws/DOCS/current/api/org/springframework/ws/server/endpoint/endpoint/adapter/methandler.html)的类级 Javadoc,以查看如何。
### [](#server-endpoint-mapping)5.4。端点映射
### 5.4.端点映射
端点映射负责将传入消息映射到适当的端点。默认情况下,一些端点映射是启用的——例如,`PayloadRootAnnotationMethodEndpointMapping``SoapActionAnnotationMethodEndpointMapping`。然而,我们首先需要研究`EndpointMapping`的一般概念。
......@@ -1718,7 +1718,7 @@ public class AnnotationOrderEndpoint {
或者,`SoapActionAnnotationMethodEndpointMapping`使用`@SoapAction`注释来标记具有特定 SOAP 操作的方法。每当带有这个`SOAPAction`头的消息出现时,都会调用该方法。
#### [](#server-ws-addressing)5.4.1。WS-Addressing
#### 5.4.1.WS-Addressing
WS-Addressing 指定了一种与传输无关的路由机制。它基于`To``Action`SOAP 头,它们分别指示 SOAP 消息的目的和意图。此外,WS-Addressing 允许你定义一个返回地址(用于正常消息和错误)和一个唯一的消息标识符,该标识符可用于相关性。有关 WS-Addressing 的更多信息,请参见[https://en.wikipedia.org/wiki/WS-Addressing](https://en.wikipedia.org/wiki/WS-Addressing)。下面的示例显示了一个 WS-Addressing 消息:
......@@ -1745,7 +1745,7 @@ WS-Addressing 指定了一种与传输无关的路由机制。它基于`To`和`A
Spring 在 Web 服务中,WS-Addressing 被实现为端点映射。通过使用此映射,可以将 WS-Addressing 操作与端点关联起来,类似于前面描述的`SoapActionAnnotationMethodEndpointMapping`
##### [](#_using_annotationactionendpointmapping)使用`AnnotationActionEndpointMapping`
##### 使用`AnnotationActionEndpointMapping`
`AnnotationActionEndpointMapping`类似于`SoapActionAnnotationMethodEndpointMapping`,但使用 WS-Addressing 头,而不是 SOAP 动作传输头。
......@@ -1786,7 +1786,7 @@ public class AnnotationOrderEndpoint {
最后,还有`messageSenders`属性,这是将响应消息发送到非匿名的、未绑定的地址所必需的。你可以在此属性中设置`MessageSender`实现,就像在`WebServiceTemplate`上一样。见[URI 和传输](#client-transports)
#### [](#server-endpoint-interceptor)5.4.2。拦截请求—`EndpointInterceptor`接口
#### 5.4.2.拦截请求—`EndpointInterceptor`接口
端点映射机制具有端点拦截器的概念。当你希望将特定功能应用于某些请求时,这些功能可能非常有用——例如,处理与安全相关的 SOAP 头或记录请求和响应消息。
......@@ -1830,7 +1830,7 @@ public class MyWsConfiguration extends WsConfigurerAdapter {
你可以在 Web 服务中使用许多标准`EndpointInterceptor`实现。此外,还有`XwsSecurityInterceptor`,它在[`XwsSecurityInterceptor`](#security-xws-security-interceptor)中进行了描述。
##### [](#_payloadlogginginterceptor_and_soapenvelopelogginginterceptor)`PayloadLoggingInterceptor`和`SoapEnvelopeLoggingInterceptor`
##### `PayloadLoggingInterceptor`和`SoapEnvelopeLoggingInterceptor`
在开发 Web 服务时,记录传入和传出的 XML 消息可能很有用。 Spring WS 通过`PayloadLoggingInterceptor``SoapEnvelopeLoggingInterceptor`类来促进这一点。前者只将消息的有效负载记录到 Commons 日志中。后者记录整个 SOAP 信封,包括 SOAP 头。下面的示例展示了如何在端点映射中定义`PayloadLoggingInterceptor`:
......@@ -1844,7 +1844,7 @@ public class MyWsConfiguration extends WsConfigurerAdapter {
对于`PayloadLoggingInterceptor`,你也可以使用`WsConfigurerAdapter`方法,如前面所述。
##### [](#_payloadvalidatinginterceptor)`PayloadValidatingInterceptor`
##### `PayloadValidatingInterceptor`
使用契约优先的开发风格的好处之一是,我们可以使用模式来验证传入和传出的 XML 消息。 Spring-WS 通过`PayloadValidatingInterceptor`促进了这一点。此拦截器需要对一个或多个 W3CXML 或 RELAXNG 模式的引用,并且可以设置为验证请求、响应或两者。
......@@ -1864,7 +1864,7 @@ public class MyWsConfiguration extends WsConfigurerAdapter {
当然,你也可以使用`WsConfigurerAdapter`方法,如前面所述,用于`PayloadValidatingInterceptor`
##### [](#_using_payloadtransforminginterceptor)使用`PayloadTransformingInterceptor`
##### 使用`PayloadTransformingInterceptor`
Spring 为了将有效负载转换为另一种 XML 格式,Web 服务提供了`PayloadTransformingInterceptor`。这个端点拦截器基于 XSLT 样式表,在支持 Web 服务的多个版本时特别有用,因为你可以将较旧的消息格式转换为较新的格式。下面的示例使用`PayloadTransformingInterceptor`:
......@@ -1880,7 +1880,7 @@ Spring 为了将有效负载转换为另一种 XML 格式,Web 服务提供了`
对于`PayloadTransformingInterceptor`,你也可以使用`WsConfigurerAdapter`方法,如前面所述。
### [](#server-endpoint-exception-resolver)5.5。处理异常
### 5.5.处理异常
Spring-WS 提供了`EndpointExceptionResolvers`,以减轻在你的消息被匹配该请求的端点处理时发生意外异常的痛苦。端点异常解析器有点类似于可以在 Web 应用程序描述符`web.xml`中定义的异常映射。然而,它们提供了一种更灵活的处理异常的方法。它们提供了有关抛出异常时调用的端点的信息。此外,处理异常的编程方式为你提供了更多关于如何适当响应的选项。你不需要通过提供异常和堆栈跟踪来暴露应用程序的内部,而是可以以任何你想要的方式处理异常——例如,通过返回带有特定错误代码和字符串的 SOAP 错误。
......@@ -1888,7 +1888,7 @@ Spring-WS 提供了`EndpointExceptionResolvers`,以减轻在你的消息被匹
除了实现`EndpointExceptionResolver`接口(这只是实现`resolveException(MessageContext, endpoint, Exception)`方法的问题)外,还可以使用所提供的实现之一。最简单的实现是`SimpleSoapExceptionResolver`,它创建一个 SOAP1.1 服务器或 SOAP1.2 接收器故障,并使用异常消息作为故障字符串。`SimpleSoapExceptionResolver`是默认值,但是可以通过显式地添加另一个解析器来重写它。
#### [](#_soapfaultmappingexceptionresolver)5.5.1。`SoapFaultMappingExceptionResolver`
#### 5.5.1.`SoapFaultMappingExceptionResolver`
`SoapFaultMappingExceptionResolver`是一种更复杂的实现。这个解析器允许你获取任何可能被抛出的异常的类名,并将其映射到一个 SOAP 错误:
......@@ -1921,7 +1921,7 @@ Spring-WS 提供了`EndpointExceptionResolvers`,以减轻在你的消息被匹
如果发生任何其他异常,它将返回默认的故障:服务器端故障,异常消息作为故障字符串。
#### [](#_using_soapfaultannotationexceptionresolver)5.5.2。使用`SoapFaultAnnotationExceptionResolver`
#### 5.5.2.使用`SoapFaultAnnotationExceptionResolver`
你还可以使用`@SoapFault`注释来注释异常类,以指示每当引发异常时应返回的 SOAP 错误。要获取这些注释,你需要将`SoapFaultAnnotationExceptionResolver`添加到应用程序上下文中。注释的元素包括错误代码枚举、错误字符串或原因以及语言。下面的示例显示了这样的例外情况:
......@@ -1953,7 +1953,7 @@ public class MyBusinessException extends Exception {
</SOAP-ENV:Envelope>
```
### [](#_server_side_testing)5.6。服务器端测试
### 5.6.服务器端测试
当涉及到测试你的 Web 服务端点时,你有两种可能的方法:
......@@ -1965,7 +1965,7 @@ public class MyBusinessException extends Exception {
第一种方法可以通过模拟框架(如 EasyMock、JMock 等)轻松实现。下一节将重点讨论如何使用 Spring Web 服务 2.0 中介绍的测试特性编写集成测试。
#### [](#_writing_server_side_integration_tests)5.6.1。编写服务器端集成测试
#### 5.6.1.编写服务器端集成测试
Spring Web 服务 2.0 引入了对创建端点集成测试的支持。在这种上下文中,端点是处理消息的类(参见[Endpoints](#server-endpoints))。
......@@ -2066,7 +2066,7 @@ public class CustomerEndpointIntegrationTest {
|**4**|在`@Before`方法中,我们使用`createClient`工厂方法创建`MockWebServiceClient`。|
|**5**|我们通过调用`sendRequest()`并使用静态导入的`RequestCreators`提供的`RequestCreator`来发送请求(请参见[using`RequestCreator`)和`RequestCreators`(#server-test-request-creator))。<br/><br/>我们还通过调用静态导入的`payload()`提供的`ResponseMatcher`(参见[using`ResponseMatcher`和`ResponseMatchers`(#server-test-response-response-matcher-matcher=“967”))来设置响应期望。但是 IDE 的代码完成功能非常有帮助。在输入`sendRequest(`之后,你的 IDE 可以为你提供一个可能的请求创建策略的列表,前提是静态导入`RequestCreators`。这同样适用于`andExpect()`,前提是静态导入`ResponseMatchers`。|
#### [](#server-test-request-creator)5.6.2。使用`RequestCreator``RequestCreators`
#### 5.6.2.使用`RequestCreator`和`RequestCreators`
最初,`MockWebServiceClient`需要为要使用的端点创建一个请求消息。客户机为此目的使用`RequestCreator`策略接口:
......@@ -2081,7 +2081,7 @@ public interface RequestCreator {
你可以编写你自己的这个接口的实现,通过使用消息工厂来创建请求消息,但是你当然不必这样做。`RequestCreators`类提供了一种基于`withPayload()`方法中的给定有效负载创建`RequestCreator`的方法。通常静态导入`RequestCreators`。
#### [](#server-test-response-matcher)5.6.3。使用`ResponseMatcher`和`ResponseMatchers`
#### 5.6.3.使用`ResponseMatcher`和`ResponseMatchers`
当端点处理了请求消息并且接收到了响应时,`MockWebServiceClient`可以验证此响应消息是否满足某些期望。客户机为此目的使用`ResponseMatcher`策略接口:
......@@ -2118,7 +2118,7 @@ mockClient.sendRequest(...).
有关`ResponseMatchers`提供的响应匹配器的更多信息,请参见[Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/server/ResponseMatchers.html)
## [](#client)6。在客户端上使用 Spring Web 服务
## 6.在客户端上使用 Spring Web 服务
Spring-WS 提供了一个客户端 Web 服务 API,该 API 允许对 Web 服务进行一致的、XML 驱动的访问。它还迎合了 Marshaller 和 Unmarshaller 的使用,这样你的服务层代码就可以专门处理 Java 对象了。
......@@ -2130,19 +2130,19 @@ Spring-WS 提供了一个客户端 Web 服务 API,该 API 允许对 Web 服务
* 允许多种运输方式
### [](#_using_the_client_side_api)6.1。使用客户端 API
### 6.1.使用客户端 API
本节描述如何使用客户端 API。有关如何使用服务器端 API,请参见[Creating a Web service with Spring-WS](#server)
#### [服务器端 WS-Addressing](#server-ws-addressing)6.1.1`WebServiceTemplate`
#### [服务器端 WS-Addressing](#server-ws-addressing)6.1.1.`WebServiceTemplate`
`WebServiceTemplate`是 Spring-WS 中用于客户端 Web 服务访问的核心类。它包含用于发送`Source`对象和以`Source``Result`接收响应消息的方法。此外,它还可以在跨传输发送对象之前将对象封送到 XML,并将任何响应 XML 重新封送到对象中。
##### [](#client-transports)URI 和 Transports
##### URI 和 Transports
`WebServiceTemplate`类使用 URI 作为消息目的地。你可以在模板本身上设置`defaultUri`属性,也可以在调用模板上的方法时显式地提供 URI。URI 解析为`WebServiceMessageSender`,它负责跨传输层发送 XML 消息。你可以使用`messageSender``messageSenders`类的属性来设置一个或多个消息发送者。
###### [](#_http_transports)HTTP 传输
###### HTTP 传输
用于通过 HTTP 发送消息的`WebServiceMessageSender`接口有两种实现方式。默认的实现是`HttpUrlConnectionMessageSender`,它使用 Java 本身提供的功能。另一种选择是`HttpComponentsMessageSender`,它使用[Apache HttpComponents HttpClient](https://hc.apache.org/httpcomponents-client-ga)。如果你需要更高级、更易用的功能(如身份验证、HTTP 连接池等),请使用后者。
......@@ -2181,7 +2181,7 @@ Spring-WS 提供了一个客户端 Web 服务 API,该 API 允许对 Web 服务
</bean>
```
###### [](#_jms_transport_2)JMS 传输
###### JMS 传输
对于通过 JMS 发送消息, Spring Web 服务提供`JmsMessageSender`。这个类使用 Spring 框架的功能将`WebServiceMessage`转换为 JMS`Message`,在`Queue``Topic`上发送它,并接收响应(如果有的话)。
......@@ -2213,7 +2213,7 @@ Spring-WS 提供了一个客户端 Web 服务 API,该 API 允许对 Web 服务
</beans>
```
###### [](#_email_transport_2)电子邮件传输
###### 电子邮件传输
Spring Web 服务还提供了一种电子邮件传输,你可以使用它通过 SMTP 发送 Web 服务消息,并通过 POP3 或 IMAP 检索它们。客户端电子邮件功能包含在`MailMessageSender`类中。这个类从请求`WebServiceMessage`创建一个电子邮件消息,并通过 SMTP 发送它。然后,它等待响应消息到达传入的 POP3 或 IMAP 服务器。
......@@ -2241,7 +2241,7 @@ Spring Web 服务还提供了一种电子邮件传输,你可以使用它通过
</beans>
```
###### [](#_xmpp_transport_2)XMPP 传输
###### XMPP 传输
Spring Web 服务 2.0 引入了一种 XMPP 传输,你可以使用它通过 XMPP 发送和接收 Web 服务消息。客户端 XMPP 功能包含在`XmppMessageSender`类中。该类从请求`WebServiceMessage`创建一个 XMPP 消息,并通过 XMPP 发送它。然后,它会监听收到的响应消息。
......@@ -2277,7 +2277,7 @@ Spring Web 服务 2.0 引入了一种 XMPP 传输,你可以使用它通过 XMP
除了消息发送者之外,`WebServiceTemplate`还需要一个 Web 服务消息工厂。SOAP 有两个消息工厂:`SaajSoapMessageFactory``AxiomSoapMessageFactory`。如果没有指定消息工厂(通过设置`messageFactory`属性), Spring-WS 默认使用`SaajSoapMessageFactory`
#### [](#_sending_and_receiving_a_webservicemessage)6.1.2。发送和接收`WebServiceMessage`
#### 6.1.2.发送和接收`WebServiceMessage`
`WebServiceTemplate`包含许多发送和接收 Web 服务消息的方便方法。有一些方法可以接受并返回`Source`,也有一些方法可以返回`Result`。此外,还有将对象封送和解封送到 XML 的方法。下面的示例向 Web 服务发送一个简单的 XML 消息:
......@@ -2333,11 +2333,11 @@ public class WebServiceClient {
注意,`WebServiceTemplate`类在配置后是线程安全的(假设它的所有依赖项也是线程安全的,这是 Spring-WS 附带的所有依赖项的情况),因此多个对象可以使用相同的共享`MailMessageSender`实例。`WebServiceTemplate`公开了一个零参数构造函数和`messageFactory``messageSender` Bean 属性,你可以使用这些属性来构造实例(通过使用 Spring 容器或普通 Java 代码)。或者,可以考虑从 Spring-WS 的`messageSender`便利基类派生,它公开了方便的 Bean 属性以实现简单的配置。(你不必扩展这个基类。它仅作为一种便利类提供。
#### [](#_sending_and_receiving_pojosmarshalling_and_unmarshalling)6.1.3。发送和接收 POJO——编组和解组
#### 6.1.3.发送和接收 POJO——编组和解组
为了方便普通 Java 对象的发送,`WebServiceTemplate`具有许多`send(..)`方法,这些方法将`Object`作为消息数据内容的参数。在`WebServiceTemplate`类中的方法`send(..)`将请求对象到 XML 的转换委托给`Marshaller`,并将响应 XML 到对象的转换委托给`Unmarshaller`。(有关编组和解组器的更多信息,请参见[the Spring Framework reference documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#oxm-marshaller-unmarshaller)。)通过使用编组器,你的应用程序代码可以专注于正在发送或接收的业务对象,而不必关注它如何表示为 XML 的详细信息。要使用编组功能,必须使用`WebServiceTemplate`类的`marshaller``unmarshaller`属性设置编组器和解组器。
#### [](#_using_webservicemessagecallback)6.1.4。使用`WebServiceMessageCallback`
#### 6.1.4.使用`WebServiceMessageCallback`
为了适应在消息上设置 SOAP 头和其他设置,`WebServiceMessageCallback`接口允许你在消息创建之后但在消息发送之前访问该消息。下面的示例演示了如何在通过编组对象创建的消息上设置 SOAP 动作头:
......@@ -2356,7 +2356,7 @@ public void marshalWithSoapActionHeader(MyObject o) {
| |请注意,你也可以使用`org.springframework.ws.soap.client.core.SoapActionCallback`来设置 SOAP 动作标头。|
|---|--------------------------------------------------------------------------------------------------------------------------|
##### [](#_ws_addressing)WS-Addressing
##### WS-Addressing
Spring 除了[服务器端 WS-Addressing](#server-ws-addressing)支持外,Web 服务还在客户端支持此规范。
......@@ -2368,7 +2368,7 @@ Spring 除了[服务器端 WS-Addressing](#server-ws-addressing)支持外,Web
webServiceTemplate.marshalSendAndReceive(o, new ActionCallback("http://samples/RequestOrder"));
```
#### [](#_using_webservicemessageextractor)6.1.5。使用`WebServiceMessageExtractor`
#### 6.1.5.使用`WebServiceMessageExtractor`
`WebServiceMessageExtractor`接口是一个低级的回调接口,你可以完全控制从接收到的`Object`中提取`Object`的过程。`WebServiceTemplate`在提供的`WebServiceMessageExtractor`上调用`extractData(..)`方法,同时与服务资源的底层连接仍处于打开状态。下面的示例显示了`WebServiceMessageExtractor`的作用:
......@@ -2389,7 +2389,7 @@ public void marshalWithSoapActionHeader(final Source s) {
}
```
### [](#_client_side_testing)6.2。客户端测试
### 6.2.客户端测试
当涉及到测试你的 Web 服务客户机(即使用`WebServiceTemplate`访问 Web 服务的类)时,你有两种可能的方法:
......@@ -2401,7 +2401,7 @@ public void marshalWithSoapActionHeader(final Source s) {
第一种方法可以通过模拟框架(如 EasyMock、JMock 等)轻松实现。下一节将重点讨论如何使用 Spring Web 服务 2.0 中介绍的测试特性编写集成测试。
#### [](#_writing_client_side_integration_tests)6.2.1。编写客户端集成测试
#### 6.2.1.编写客户端集成测试
Spring Web 服务 2.0 引入了对创建 Web 服务客户端集成测试的支持。在这种情况下,客户机是使用`WebServiceTemplate`访问 Web 服务的类。
......@@ -2514,7 +2514,7 @@ public class CustomerClientIntegrationTest {
|**6**|我们在`CustomerClient`上调用`getCustomerCount()`,从而使用`WebServiceTemplate`。到目前为止,模板已经为“测试模式”设置好了,因此这个方法调用不会产生真正的连接。我们还根据方法调用的结果进行了一些 JUnit 断言。|
|**7**|我们在`MockWebServiceServer`上调用`verify()`,以验证是否实际收到了预期的消息。|
#### [](#client-test-request-matcher)6.2.2。使用`RequestMatcher`和`RequestMatchers`
#### 6.2.2.使用`RequestMatcher`和`RequestMatchers`
为了验证请求消息是否满足某些期望,`MockWebServiceServer`使用`RequestMatcher`策略接口。此接口定义的契约如下:
......@@ -2552,7 +2552,7 @@ mockServer.expect(connectionTo("http://example.com")).
有关`RequestMatchers`提供的请求匹配器的更多信息,请参见[Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html)
#### [](#client-test-response-creator)6.2.3。使用`ResponseCreator`和`ResponseCreators`
#### 6.2.3.使用`ResponseCreator`和`ResponseCreators`
当请求消息经过验证并满足已定义的期望时,`MockWebServiceServer`将为`WebServiceTemplate`创建一个要使用的响应消息。服务器为此目的使用`ResponseCreator`策略接口:
......@@ -2580,7 +2580,7 @@ public interface ResponseCreator {
有关`RequestMatchers`提供的请求匹配器的更多信息,请参见[Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html)
## [](#security)7。使用 Spring-WS 保护你的 Web 服务
## 7.使用 Spring-WS 保护你的 Web 服务
本章将解释如何将 WS-Security 方面添加到 Web 服务中。我们关注 WS-Security 的三个不同领域:
......@@ -2595,7 +2595,7 @@ public interface ResponseCreator {
| |请注意,WS-Security(特别是加密和签名)需要大量的内存,并且可能会降低性能。如果性能对你很重要,那么你可能想要考虑不使用 WS-Security 或使用基于 HTTP 的安全性。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#security-xws-security-interceptor)7.1。[Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html)
###
`XwsSecurityInterceptor`是一个`EndpointInterceptor`(参见[拦截请求-`EndpointInterceptor`接口](#server-endpoint-interceptor)),它基于 Sun 的 XML 和 Web 服务安全包。这个 WS-Security 实现是 Java Web 服务开发人员包([Java WSDP](http://java.sun.com/webservices/))的一部分。
......@@ -2628,7 +2628,7 @@ public interface ResponseCreator {
这个拦截器是通过使用 Classpath 上的`securityPolicy.xml`文件来配置的。它使用了稍后在文件中定义的两个回调处理程序。
#### [](#keystore)7.1.1。密钥存储库
#### 7.1.1.密钥存储库
对于大多数加密操作,你都使用标准的`java.security.KeyStore`对象。这些操作包括证书验证、消息签名、签名验证和加密。它们不包括用户名和时间戳验证。本节旨在为你提供一些关于密钥存储库和 Java 工具的背景知识,你可以使用这些工具将密钥和证书存储在密钥存储库文件中。这些信息大多与 Spring-WS 无关,而是与 Java 的一般加密特性有关。
......@@ -2640,11 +2640,11 @@ public interface ResponseCreator {
* **可信证书**:这些 X509 证书被称为“受信任证书”,因为密钥存储库所有者相信证书中的公钥确实属于证书的所有者。在 WS-Security 中,这些证书用于证书验证、签名验证和加密。
##### [](#_using_keytool)使用`keytool`
##### 使用`keytool`
`keytool`程序是一个密钥和证书管理实用程序,它与你的 Java 虚拟机一起提供。你可以使用此工具创建新的密钥库,向它们添加新的私钥和证书,等等。提供`keytool`命令的完整引用超出了本文档的范围,但是你可以在命令行中找到[here](http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/keytool.html)或使用`@XmlRootElement`命令的引用。
##### [](#_using_keystorefactorybean)使用`KeyStoreFactoryBean`
##### 使用`KeyStoreFactoryBean`
要使用 Spring 配置轻松加载密钥库,可以使用`KeyStoreFactoryBean`。它有一个资源位置属性,你可以将其设置为指向要加载的密钥库的路径。可以给出一个密码来检查密钥存储库数据的 Integrity。如果没有给出密码,则不执行 Integrity 检查。下面的清单配置了`KeyStoreFactoryBean`:
......@@ -2658,7 +2658,7 @@ public interface ResponseCreator {
| |如果没有指定 location 属性,就会创建一个新的空密钥库,这很可能不是你想要的。|
|---|----------------------------------------------------------------------------------------------------------------------|
##### [](#security-key-store-callback-handler)KeystoRecallBackHandler
##### KeystoRecallBackHandler
要在`XwsSecurityInterceptor`中使用密钥存储库,你需要定义`KeyStoreCallbackHandler`。这个回调有三个类型为`keystore`的属性:(`keyStore``trustStore`,和`symmetricStore`)。处理程序所使用的确切存储取决于该处理程序要执行的加密操作。对于私钥操作,使用`keyStore`。对于对称的键操作,使用`symmetricStore`。为了确定信任关系,使用了`trustStore`。下表表明了这一点:
......@@ -2709,11 +2709,11 @@ public interface ResponseCreator {
下面的部分指出了`KeyStoreCallbackHandler`可以在哪里使用,以及为特定的加密操作设置哪些属性。
#### [](#_authentication)7.1.2。认证
#### 7.1.2.认证
正如[本章导言](#security)中所述,身份验证是确定主体是否是他们所声称的人的任务。在 WS-Security 中,身份验证可以采取两种形式:使用用户名和密码令牌(使用纯文本密码或密码摘要)或使用 X509 证书。
##### [](#_plain_text_username_authentication)纯文本用户名身份验证
##### 纯文本用户名身份验证
最简单的用户名身份验证形式使用纯文本密码。在这种情况下,SOAP 消息包含一个`UsernameToken`元素,它本身包含一个`Username`元素和一个`Password`元素,它包含纯文本密码。纯文本身份验证可以与 HTTP 服务器提供的基本身份验证进行比较。
......@@ -2738,7 +2738,7 @@ public interface ResponseCreator {
* [`JaasPlainTextPasswordValidationCallbackHandler`](#using-jaasplaintextpasswordvalidationcallbackhandler)
###### [](#security-simple-password-validation-callback-handler)使用`SimplePasswordValidationCallbackHandler`
###### 使用`SimplePasswordValidationCallbackHandler`
最简单的密码验证处理程序是`SimplePasswordValidationCallbackHandler`。此处理程序针对内存中的`Properties`对象验证密码,你可以将该对象指定为`users`属性:
......@@ -2755,7 +2755,7 @@ public interface ResponseCreator {
在这种情况下,我们只允许用户“BERT”使用密码“ERNIE”登录。
###### [](#using-springplaintextpasswordvalidationcallbackhandler)使用`SpringPlainTextPasswordValidationCallbackHandler`
###### 使用`SpringPlainTextPasswordValidationCallbackHandler`
`SpringPlainTextPasswordValidationCallbackHandler`使用[Spring Security](https://spring.io/projects/spring-security)对用户进行身份验证。描述 Spring 安全性超出了本文的范围,但它是一个成熟的安全框架。你可以在[Spring Security reference documentation](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/)中阅读有关它的更多信息。
......@@ -2781,7 +2781,7 @@ public interface ResponseCreator {
</beans>
```
###### [](#using-jaasplaintextpasswordvalidationcallbackhandler)使用`JaasPlainTextPasswordValidationCallbackHandler`
###### 使用`JaasPlainTextPasswordValidationCallbackHandler`
`JaasPlainTextPasswordValidationCallbackHandler`基于标准[Java 身份验证和授权服务](http://java.sun.com/products/jaas/)。提供对 JAAS 的完整介绍超出了本文的范围,但是[好的教程](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html)是可用的。
......@@ -2798,7 +2798,7 @@ public interface ResponseCreator {
在这种情况下,回调处理程序使用名为`LoginContext``MyLoginModule`。这个模块应该在`jaas.config`文件中定义,如[前面提到的教程](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html)中所解释的那样。
##### [](#_digest_username_authentication)摘要用户名身份验证
##### 摘要用户名身份验证
在使用密码摘要时,SOAP 消息还包含一个`UsernameToken`元素,该元素本身包含一个`Username`元素和一个`Password`元素。不同之处在于,密码不是以纯文本的形式发送的,而是以摘要的形式发送的。收件人将此摘要与他根据用户的已知密码计算出的摘要进行比较,如果它们是相同的,则对用户进行身份验证。这种方法类似于 HTTP 服务器提供的摘要身份验证。
......@@ -2814,11 +2814,11 @@ public interface ResponseCreator {
如果不存在用户名令牌,`XwsSecurityInterceptor`将向发送方返回一个 SOAP 错误。如果它存在,它将向注册的处理程序发送一个`PasswordValidationCallback`和一个`DigestPasswordRequest`。在 Spring-WS 中,有两个类处理这个特定的回调:`SimplePasswordValidationCallbackHandler``SpringDigestPasswordValidationCallbackHandler`
###### [](#_using_simplepasswordvalidationcallbackhandler)使用`SimplePasswordValidationCallbackHandler`
###### 使用`SimplePasswordValidationCallbackHandler`
`SimplePasswordValidationCallbackHandler`既可以处理纯文本密码,也可以处理密码摘要。在[using`SimplePasswordValidationCallbackHandler`](#security-simple-password-validation-callback-handler)中进行了描述。
###### [](#_using_springdigestpasswordvalidationcallbackhandler)使用`SpringDigestPasswordValidationCallbackHandler`
###### 使用`SpringDigestPasswordValidationCallbackHandler`
`SpringDigestPasswordValidationCallbackHandler`需要 Spring 证券`UserDetailService`才能操作。它使用此服务检索令牌中指定的用户的密码。然后将包含在此 Details 对象中的密码摘要与消息中的摘要进行比较。如果它们相等,则用户已成功地进行了身份验证,并且`UsernamePasswordAuthenticationToken`存储在`SecurityContextHolder`中。你可以使用`userDetailsService`属性设置服务。此外,还可以设置`userCache`属性,以缓存已加载的用户详细信息。下面的示例展示了如何做到这一点:
......@@ -2833,7 +2833,7 @@ public interface ResponseCreator {
</beans>
```
##### [](#security-certificate-authentication)证书认证
##### 证书认证
一种更安全的认证方式是使用 X509 证书。在此场景中,SOAP 消息包含`BinarySecurityToken`,其中包含 x509 证书的 base64 编码版本。该证书由收件人使用以进行身份验证。存储在消息中的证书也用于对消息进行签名(参见[验证签名](#security-verifying-signatures))。
......@@ -2858,7 +2858,7 @@ public interface ResponseCreator {
| |在大多数情况下,证书身份验证之前应该有证书验证,因为你希望仅针对有效的证书进行身份验证。无效的证书,例如过期日期已经过的证书或不在受信任证书存储区中的证书,应该被忽略。<br/><br/>在 Spring-WS 术语中,这意味着`SpringCertificateValidationCallbackHandler``JaasCertificateValidationCallbackHandler`应该在`KeyStoreCallbackHandler`之前。这可以通过在`XwsSecurityInterceptor`的配置中设置`callbackHandlers`属性的顺序来实现:<br/><br/>```<br/><bean id="wsSecurityInterceptor"<br/> class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"><br/> <property name="policyConfiguration" value="classpath:securityPolicy.xml"/><br/> <property name="callbackHandlers"><br/> <list><br/> <ref bean="keyStoreHandler"/><br/> <ref bean="springSecurityHandler"/><br/> </list><br/> </property><br/></bean><br/>```<br/>拦截器首先使用密钥存储库确定消息中的证书是否有效,然后对其进行身份验证。|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
###### [](#using-keystorecallbackhandler)使用`KeyStoreCallbackHandler`
###### 使用`KeyStoreCallbackHandler`
`KeyStoreCallbackHandler`使用标准的 Java 密钥存储库来验证证书。此证书验证过程包括以下步骤:。
......@@ -2885,7 +2885,7 @@ public interface ResponseCreator {
使用前面示例中显示的设置,要验证的证书必须位于信任存储区本身,或者信任存储区必须包含颁发证书的证书颁发机构。
###### [](#using-springcertificatevalidationcallbackhandler)使用`SpringCertificateValidationCallbackHandler`
###### 使用`SpringCertificateValidationCallbackHandler`
`SpringCertificateValidationCallbackHandler`需要 Spring 证券`AuthenticationManager`才能操作。它使用此管理器对它创建的`X509AuthenticationToken`进行身份验证。配置的身份验证管理器需要提供一个能够处理这个令牌的提供者(通常是`X509AuthenticationProvider`的实例)。如果身份验证成功,则将令牌存储在`SecurityContextHolder`中。你可以使用`authenticationManager`属性设置身份验证管理器:
......@@ -2916,7 +2916,7 @@ public interface ResponseCreator {
在这种情况下,我们使用自定义用户详细信息服务来基于证书获得身份验证详细信息。有关针对 X509 证书的身份验证的更多信息,请参见[Spring Security reference documentation](http://www.springframework.org/security)
###### [](#using-jaascertificatevalidationcallbackhandler)使用`JaasCertificateValidationCallbackHandler`
###### 使用`JaasCertificateValidationCallbackHandler`
`JaasCertificateValidationCallbackHandler`需要`loginContextName`才能操作。它使用证书的这个名称和`X500Principal`创建一个新的 JAAS`LoginContext`。这意味着此回调处理程序与处理 X500 主体的任何 JAAS`LoginModule`集成。
......@@ -2931,11 +2931,11 @@ public interface ResponseCreator {
在这种情况下,回调处理程序使用名为`LoginContext``MyLoginModule`。这个模块应该在你的`jaas.config`文件中定义,并且应该能够针对 X500 主体进行身份验证。
#### [](#_digital_signatures)7.1.3。数字签名
#### 7.1.3.数字签名
消息的数字签名是基于文档和签名者的私钥的一条信息。与 WS-Security 中的签名相关的两个主要任务是:验证签名和签名消息。
##### [](#security-verifying-signatures)验证签名
##### 验证签名
[基于证书的身份验证](#security-certificate-authentication)一样,已签名的消息包含`BinarySecurityToken`,其中包含用于对消息进行签名的证书。此外,它还包含一个`SignedInfo`块,该块指示消息的哪一部分已签名。
......@@ -2949,7 +2949,7 @@ public interface ResponseCreator {
如果签名不存在,`XwsSecurityInterceptor`将向发送方返回一个 SOAP 错误。如果存在,它将向已注册的处理程序触发`SignatureVerificationKeyCallback`。在 Spring-WS 中,有一个类处理这个特定的回调:`KeyStoreCallbackHandler`
###### [](#_using_keystorecallbackhandler)使用`KeyStoreCallbackHandler`
###### 使用`KeyStoreCallbackHandler`
[KeystoRecallBackHandler](#security-key-store-callback-handler)中所述,`KeyStoreCallbackHandler`使用`java.security.KeyStore`来处理各种加密回调,包括签名验证。对于签名验证,处理程序使用`trustStore`属性:
......@@ -2966,7 +2966,7 @@ public interface ResponseCreator {
</beans>
```
##### [](#_signing_messages)签名消息
##### 签名消息
签名消息时,`XwsSecurityInterceptor``BinarySecurityToken`添加到消息中。它还添加了一个`SignedInfo`块,该块指示消息的哪一部分已签名。
......@@ -2980,7 +2980,7 @@ public interface ResponseCreator {
`XwsSecurityInterceptor`向注册处理程序发送`SignatureKeyCallback`。在 Spring-WS 中,`KeyStoreCallbackHandler`类处理这个特定的回调。
###### [](#_using_keystorecallbackhandler_2)使用`KeyStoreCallbackHandler`
###### 使用`KeyStoreCallbackHandler`
[KeystoRecallBackHandler](#security-key-store-callback-handler)中所述,`KeyStoreCallbackHandler`使用`java.security.KeyStore`来处理各种加密回调,包括签名消息。对于添加签名,处理程序使用`keyStore`属性。此外,你必须设置`privateKeyPassword`属性来解锁用于签名的私钥。下面的示例使用`KeyStoreCallbackHandler`:
......@@ -2998,11 +2998,11 @@ public interface ResponseCreator {
</beans>
```
#### [](#_decryption_and_encryption)7.1.4。解密和加密
#### 7.1.4.解密和加密
加密时,将消息转换为只能使用适当密钥读取的窗体。可以对消息进行解密,以显示原始的可读消息。
##### [](#_decryption)解密
##### 解密
要解密传入的 SOAP 消息,安全策略文件应该包含`RequireEncryption`元素。该元素还可以携带一个`EncryptionTarget`元素,该元素指示消息的哪一部分应该加密,并携带一个`SymmetricKey`,指示应该使用共享秘密而不是常规私钥来解密消息。你可以读取对其他元素[here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951)的描述。下面的示例使用`RequireEncryption`元素:
......@@ -3014,7 +3014,7 @@ public interface ResponseCreator {
如果传入消息未加密,`XwsSecurityInterceptor`将向发送方返回一个 SOAP ault。如果存在,它将向已注册的处理程序触发`DecryptionKeyCallback`。在 Spring-WS 中,`KeyStoreCallbackHandler`类处理这个特定的回调。
###### [](#_using_keystorecallbackhandler_3)使用`KeyStoreCallbackHandler`
###### 使用`KeyStoreCallbackHandler`
[KeystoRecallBackHandler](#security-key-store-callback-handler)中所述,`KeyStoreCallbackHandler`使用`java.security.KeyStore`来处理各种加密回调,包括解密。对于解密,处理程序使用`keyStore`属性。此外,你必须设置`privateKeyPassword`属性来解锁用于解密的私钥。对于基于对称密钥的解密,它使用`symmetricStore`。下面的示例使用`KeyStoreCallbackHandler`:
......@@ -3032,7 +3032,7 @@ public interface ResponseCreator {
</beans>
```
##### [](#_encryption)加密
##### 加密
要对传出的 SOAP 消息进行加密,安全策略文件应该包含一个`Encrypt`元素。该元素还可以携带一个`EncryptionTarget`元素,该元素指示消息的哪一部分应该加密,以及一个`SymmetricKey`表示应该使用共享秘密而不是常规公钥来加密消息。你可以读取对其他元素[here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951)的描述。下面的示例使用`Encrypt`元素:
......@@ -3044,7 +3044,7 @@ public interface ResponseCreator {
`XwsSecurityInterceptor`向注册处理程序发送`EncryptionKeyCallback`,以检索加密信息。在 Spring-WS 中,`KeyStoreCallbackHandler`类处理这个特定的回调。
###### [](#_using_keystorecallbackhandler_4)使用`KeyStoreCallbackHandler`
###### 使用`KeyStoreCallbackHandler`
正如[KeystoRecallBackHandler](#security-key-store-callback-handler)中所描述的,`KeyStoreCallbackHandler`使用`java.security.KeyStore`来处理各种加密回调,包括加密。对于基于公钥的加密,处理程序使用`trustStore`属性。对于基于对称密钥的加密,它使用`symmetricStore`。下面的示例使用`KeyStoreCallbackHandler`:
......@@ -3061,7 +3061,7 @@ public interface ResponseCreator {
</beans>
```
#### [](#security-xws-exception-handling)7.1.5。安全异常处理
#### 7.1.5.安全异常处理
当一个 securement 或验证操作失败时,`XwsSecurityInterceptor`分别抛出一个`WsSecuritySecurementException``WsSecurityValidationException`。这些异常绕过[标准异常处理机制](#server-endpoint-exception-resolver),但由拦截器本身处理。
......@@ -3072,7 +3072,7 @@ public interface ResponseCreator {
| |`handleSecurementException``handleValidationException`都是受保护的方法,你可以覆盖该方法以更改其默认行为。|
|---|------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#security-wss4j-security-interceptor)7.2。使用`Wss4jSecurityInterceptor`
### 7.2.使用`Wss4jSecurityInterceptor`
`Wss4jSecurityInterceptor`是基于[Apache’s WSS4J](https://ws.apache.org/wss4j/)`EndpointInterceptor`(参见[拦截请求-`EndpointInterceptor`接口](# 服务器-端点-拦截器))。
......@@ -3086,7 +3086,7 @@ WSS4J 实现了以下标准:
此拦截器支持由`AxiomSoapMessageFactory``SaajSoapMessageFactory`创建的消息。
#### [](#_configuring_wss4jsecurityinterceptor)7.2.1。配置`Wss4jSecurityInterceptor`
#### 7.2.1.配置`Wss4jSecurityInterceptor`
WSS4J 不使用外部配置文件。拦截器完全由属性配置。该拦截器调用的验证和安全操作分别通过`validationActions``securementActions`属性指定。动作以空格分隔的字符串传递。下面的清单展示了一个配置示例:
......@@ -3122,13 +3122,13 @@ WSS4J 不使用外部配置文件。拦截器完全由属性配置。该拦截
行动的顺序是重要的,并由拦截器强制执行。如果其安全操作的执行顺序与`validationActions`指定的顺序不同,则拦截器将拒绝传入的 SOAP 消息。
#### [](#_handling_digital_certificates)7.2.2。处理数码证书
#### 7.2.2.处理数码证书
对于需要与密钥库或证书处理交互的加密操作(签名、加密和解密操作),WSS4J 需要`org.apache.ws.security.components.crypto.Crypto`的实例。
`Crypto`实例可以从 wss4j 的`CryptoFactory`获得,或者更方便地使用 Spring-ws`CryptoFactoryBean`
##### [](#_cryptofactorybean)CryptoFactoryBean
##### CryptoFactoryBean
Spring-WS 提供了一种方便的工厂 Bean,`CryptoFactoryBean`,它通过强类型属性(首选)或通过`Properties`对象构造和配置`Crypto`实例。
......@@ -3143,17 +3143,17 @@ Spring-WS 提供了一种方便的工厂 Bean,`CryptoFactoryBean`,它通过
</bean>
```
#### [](#_authentication_2)7.2.3。认证
#### 7.2.3.认证
本节讨论如何使用`Wss4jSecurityInterceptor`进行身份验证。
##### [](#_validating_username_token)验证用户名令牌
##### 验证用户名令牌
Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此外,还提供了一个简单的回调处理程序`SimplePasswordValidationCallbackHandler`,用内存中的`Properties`对象配置用户和密码。
回调处理程序是通过`Wss4jSecurityInterceptor`属性的`validationCallbackHandler`配置的。
###### [](#_using_simplepasswordvalidationcallbackhandler_2)使用`SimplePasswordValidationCallbackHandler`
###### 使用`SimplePasswordValidationCallbackHandler`
`SimplePasswordValidationCallbackHandler`针对内存中的`Properties`对象验证纯文本和摘要用户名令牌。你可以按以下方式配置它:
......@@ -3168,7 +3168,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
###### [](#_using_springsecuritypasswordvalidationcallbackhandler)使用`SpringSecurityPasswordValidationCallbackHandler`
###### 使用`SpringSecurityPasswordValidationCallbackHandler`
`SpringSecurityPasswordValidationCallbackHandler`通过使用 Spring 安全性`UserDetailService`来操作,从而验证纯文本和摘要密码。它使用此服务检索令牌中指定的用户的密码(或密码摘要)。然后将这个 Details 对象中包含的密码(或密码摘要)与消息中的摘要进行比较。如果它们相等,则用户已成功地进行了身份验证,并且`UsernamePasswordAuthenticationToken`存储在`SecurityContextHolder`中。你可以使用`userDetailsService`设置服务。此外,你可以设置`userCache`属性,以缓存已加载的用户详细信息,如下所示:
......@@ -3183,7 +3183,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</beans>
```
##### [](#_adding_username_token)添加用户名令牌
##### 添加用户名令牌
向传出消息添加用户名令牌就像在`Wss4jSecurityInterceptor``securementActions`属性中添加`UsernameToken`并指定`securementUsername``securementPassword`一样简单。
......@@ -3213,7 +3213,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
##### [](#_certificate_authentication)证书认证
##### 证书认证
由于证书认证类似于数字签名,WSS4J 将其作为签名验证和安全的一部分来处理。具体地说,`securementSignatureKeyIdentifier`属性必须设置为`DirectReference`,以便指示 WSS4J 生成包含 X509 证书的`BinarySecurityToken`元素,并将其包含在传出消息中。证书的名称和密码分别通过`securementUsername``securementPassword`属性传递,如下例所示:
......@@ -3250,11 +3250,11 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
有关更多详细信息,请参见[数字签名](#security-wss4j-digital-signatures)
#### [](#_security_timestamps)7.2.4。安全时间戳
#### 7.2.4.安全时间戳
本节描述`Wss4jSecurityInterceptor`中可用的各种时间戳选项。
##### [](#_validating_timestamps)验证时间戳
##### 验证时间戳
要验证时间戳,将`Timestamp`添加到`validationActions`属性。通过将`timestampStrict`设置为`true`,并通过设置`timeToLive`属性,指定服务器端的实时(默认:300),可以覆盖由 SOAP 消息的发起者指定的时间戳语义。拦截器总是拒绝已经过期的时间戳,无论`timeToLive`的值是多少。
......@@ -3268,7 +3268,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
##### [](#_adding_timestamps)添加时间戳
##### 添加时间戳
`Timestamp`添加到`securementActions`属性会在传出消息中生成一个时间戳头。`timestampPrecisionInMilliseconds`属性指定生成的时间戳的精度是否以毫秒为单位。默认值是`true`。以下清单添加了一个时间戳:
......@@ -3279,11 +3279,11 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
#### [](#security-wss4j-digital-signatures)7.2.5。数字签名
#### 7.2.5.数字签名
本节介绍`Wss4jSecurityInterceptor`中可用的各种签名选项。
##### [](#_verifying_signatures)验证签名
##### 验证签名
要指示`Wss4jSecurityInterceptor``validationActions`必须包含`Signature`操作。此外,`validationSignatureCrypto`属性必须指向包含发起者的公共证书的密钥库:
......@@ -3299,7 +3299,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
##### [](#_signing_messages_2)签名消息
##### 签名消息
通过将`Signature`动作添加到`securementActions`中,可以对发出的消息进行签名。要使用的私钥的别名和密码分别由`securementUsername``securementPassword`属性指定。`securementSignatureCrypto`必须指向包含私钥的密钥库:
......@@ -3334,7 +3334,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
如果请求中没有其他元素的本地名称`Body`,则 SOAP 名称空间标识符可以为空(`{}`)。
##### [](#_signature_confirmation)签名确认
##### 签名确认
通过将`enableSignatureConfirmation`设置为`true`,可以启用签名确认。请注意,签名确认操作跨越了请求和响应。这意味着,即使没有相应的安全操作,`secureResponse``validateRequest`也必须设置为`true`(这是默认值)。下面的示例将`enableSignatureConfirmation`属性设置为`true`:
......@@ -3351,11 +3351,11 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
#### [](#_decryption_and_encryption_2)7.2.6。解密和加密
#### 7.2.6.解密和加密
本节介绍`Wss4jSecurityInterceptor`中可用的各种解密和加密选项。
##### [](#_decryption_2)解密
##### 解密
解密传入的 SOAP 消息需要将`Encrypt`动作添加到`validationActions`属性中。配置的其余部分取决于消息中出现的关键信息。(这是因为 WSS4J 只需要对加密的密钥进行加密,而嵌入的密钥名称验证则委托给回调处理程序。
......@@ -3398,7 +3398,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
</bean>
```
##### [](#_encryption_2)加密
##### 加密
`Encrypt`添加到`securementActions`中,可以对传出的消息进行加密。通过设置`securementEncryptionUser`属性,你可以设置用于加密的证书的别名。通过`securementEncryptionCrypto`属性访问证书所在的密钥存储库。由于加密依赖于公共证书,因此不需要传递密码。下面的示例使用`securementEncryptionCrypto`属性:
......@@ -3455,20 +3455,20 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此
要指定没有名称空间的元素,请使用值`Null`(区分大小写)作为名称空间名称。如果没有指定列表,那么处理程序将默认以`Content`模式加密 SOAP 主体。
#### [](#_security_exception_handling)7.2.7。安全异常处理
#### 7.2.7.安全异常处理
`Wss4jSecurityInterceptor`的异常处理与`XwsSecurityInterceptor`的异常处理相同。有关更多信息,请参见[安全异常处理](#security-xws-exception-handling)
# [](#resources)iii。其他资源
# iii.其他资源
除了这个参考文档之外,还有许多其他资源可以帮助你了解如何使用 Spring Web 服务。本节列举了这些额外的第三方资源。
## [](#_bibliography)书目
## 书目
* [Waldo-94]Jim Waldo,Ann Wollrath 和 Sam Kendall。*关于分布式计算的一个注记*。Springer Verlag。1994
* []()[高山]Steve Loughran&Edmund Smith。*重新思考 Java SOAP 堆栈*。2005 年 5 月 17 日。2005 年 IEEE Telephone Laboratories,Inc.
* [高山]Steve Loughran&Edmund Smith。*重新思考 Java SOAP 堆栈*。2005 年 5 月 17 日。2005 年 IEEE Telephone Laboratories,Inc.
* []()[effective-Enterprise-java]Ted Neward。Scott Meyers。*有效的 EnterpriseJava*。Addison-Wesley。2004
* [effective-Enterprise-java]Ted Neward。Scott Meyers。*有效的 EnterpriseJava*。Addison-Wesley。2004
* []()[Effective-xml]Elliotte Rusty Harold。Scott Meyers。*有效 XML*。Addison-Wesley。2004
\ No newline at end of file
* [Effective-xml]Elliotte Rusty Harold。Scott Meyers。*有效 XML*。Addison-Wesley。2004
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册