1. Обзор
Java API для веб-служб XML (JAX-WS) - это стандартизированный API-интерфейс для создания и использования веб-служб SOAP (Simple Object Access Protocol).
В этой статье мы создадим веб-сервис SOAP и подключимся к нему с помощью JAX-WS.
2. МЫЛО
SOAP - это спецификация XML для отправки сообщений по сети.
SOAP тяжело работает с XML, поэтому лучше всего его использовать с инструментами/средами JAX-WS - это инфраструктура, которая упрощает использование SOAP. Это часть стандартной Java.
3. Сверху вниз против снизу вверх
Существует два способа создания веб-сервисов SOAP. Мы можем пойти с подходом сверху вниз или снизу вверх.
При нисходящем (сначала контрактном) подходе создается документ WSDL, а необходимые классы Java генерируются из WSDL. В восходящем (контракт-последний) подходе,
С другой стороны, поскольку ваш WSDL генерируется из классов Java, любое изменение в коде может вызвать изменение в WSDL. Это не относится к нисходящему подходу.
4. Язык определения веб-сервисов (WSDL)
WSDL - определение контракта доступных сервисов. Это спецификация входных/выходных сообщений и способ вызова веб-службы. Он не зависит от языка и определен в XML.
Давайте посмотрим на основные элементы документа WSDL.
4.1. Определения
Элемент definitions является корневым элементом всех документов WSDL. Он определяет имя, пространство имен и т. Д. Службы и, как вы можете видеть, может быть довольно просторным
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://jaxws.baeldung.com/"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsp1__2="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://jaxws.baeldung.com/"
name="EmployeeService">
...
</definitions>
4.2. Типы
Элемент types определяет типы данных, используемые веб-сервисом. WSDL использует XSD (определение схемы XML) в качестве системы типов, которая помогает с функциональной совместимостью:
<definitions ...>
...
<types>
<xsd:schema>
<xsd:import namespace="http://jaxws.baeldung.com/"
schemaLocation = "http://localhost:8080/employeeservice?xsd=1"/>
</xsd:schema>
</types>
...
</definitions>
4.3. Сообщения
Элемент message обеспечивает абстрактное определение передаваемых данных. Каждый элемент message описывает ввод или вывод метода службы и возможные исключения:
<definitions ...>
...
<message name="getEmployee">
<part name="parameters" element="tns:getEmployee"/>
</message>
<message name="getEmployeeResponse">
<part name="parameters" element="tns:getEmployeeResponse"/>
</message>
<message name="EmployeeNotFound">
<part name="fault" element="tns:EmployeeNotFound"/>
</message>
...
</definitions>
4.4. Операции и типы портов
Элемент portType описывает каждую операцию operation , которая может быть выполнена, и все задействованные элементы message . Например, операция getEmployee указывает запрос input , output и возможное исключение fault , выданное веб-службой operation :
<definitions ...>
...
<portType name="EmployeeService">
<operation name="getEmployee">
<input
wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeRequest"
message="tns:getEmployee"/>
<output
wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeResponse"
message="tns:getEmployeeResponse"/>
<fault message="tns:EmployeeNotFound" name="EmployeeNotFound"
wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployee/Fault/EmployeeNotFound"/>
</operation>
....
</portType>
...
</definitions>
4.5. Наручники
Элемент binding предоставляет подробности протокола и формата данных для каждого portType :
<definitions ...>
...
<binding name="EmployeeServiceImplPortBinding"
type="tns:EmployeeService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"/>
<operation name="getEmployee">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
<fault name="EmployeeNotFound">
<soap:fault name="EmployeeNotFound" use="literal"/>
</fault>
</operation>
...
</binding>
...
</definitions>
4.6. Услуги и порты
Элемент service определяет порты, поддерживаемые веб-службой.
Элемент port в service определяет name , binding и адрес службы:
<definitions ...>
...
<service name="EmployeeService">
<port name="EmployeeServiceImplPort"
binding="tns:EmployeeServiceImplPortBinding">
<soap:address
location="http://localhost:8080/employeeservice"/>
</port>
</service>
...
</definitions>
5. Подход сверху вниз (контракт-первый)
Давайте начнем с нисходящего подхода, создав файл WSDL.
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://topdown.server.jaxws.baeldung.com/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://topdown.server.jaxws.baeldung.com/"
qname="EmployeeServiceTopDown">
<types>
<xsd:schema
targetNamespace="http://topdown.server.jaxws.baeldung.com/">
<xsd:element name="countEmployeesResponse" type="xsd:int"/>
</xsd:schema>
</types>
<message name="countEmployees">
</message>
<message name="countEmployeesResponse">
<part name="parameters" element="tns:countEmployeesResponse"/>
</message>
<portType name="EmployeeServiceTopDown">
<operation name="countEmployees">
<input message="tns:countEmployees"/>
<output message="tns:countEmployeesResponse"/>
</operation>
</portType>
<binding name="EmployeeServiceTopDownSOAP"
type="tns:EmployeeServiceTopDown">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"/>
<operation name="countEmployees">
<soap:operation
soapAction="http://topdown.server.jaxws.baeldung.com/ EmployeeServiceTopDown/countEmployees"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="EmployeeServiceTopDown">
<port name="EmployeeServiceTopDownSOAP"
binding="tns:EmployeeServiceTopDownSOAP">
<soap:address
location="http://localhost:8080/employeeservicetopdown"/>
</port>
</service>
</definitions>
5.1. Генерация исходных файлов веб-службы из WSDL
Чтобы сгенерировать исходные файлы веб-службы из документа WSDL, мы можем использовать инструмент wsimport , который является частью JDK (по ссылке:/java-home-on-windows-7-8-10-mac-os-x-linux[$ JAVA__HOME]/BIN).
Из командной строки:
wsimport -s . -p com.baeldung.jaxws.server.topdown employeeservicetopdown.wsdl
Используемые параметры командной строки: -p указывает целевой пакет. -s указывает, куда поместить сгенерированные исходные файлы.
Сгенерированные файлы:
-
EmployeeServiceTopDown.java - это интерфейс конечной точки сервиса
(SEI), который содержит определения методов ** ObjectFactory.java - содержит фабричные методы для создания экземпляров
Схема производных классов программно ** EmployeeServiceTopDown Service.java__ - это класс поставщика услуг
который может использоваться клиентом JAX-WS
5.2. Интерфейс конечной точки веб-службы
Инструмент wsimport создал интерфейс конечной точки веб-службы EmployeeServiceTopDown . Он объявляет методы веб-службы:
@WebService(
name = "EmployeeServiceTopDown",
targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
ObjectFactory.class
})
public interface EmployeeServiceTopDown {
@WebMethod(
action = "http://topdown.server.jaxws.baeldung.com/"
+ "EmployeeServiceTopDown/countEmployees")
@WebResult(
name = "countEmployeesResponse",
targetNamespace = "http://topdown.server.jaxws.baeldung.com/",
partName = "parameters")
public int countEmployees();
}
5.3. Реализация веб-сервиса
Инструмент wsimport создал структуру веб-сервиса. Мы должны создать реализацию веб-сервиса:
@WebService(
name = "EmployeeServiceTopDown",
endpointInterface = "com.baeldung.jaxws.server.topdown.EmployeeServiceTopDown",
targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
public class EmployeeServiceTopDownImpl
implements EmployeeServiceTopDown {
@Inject
private EmployeeRepository employeeRepositoryImpl;
@WebMethod
public int countEmployees() {
return employeeRepositoryImpl.count();
}
}
6. Подход снизу вверх (контракт-последний)
При подходе снизу вверх мы должны создать как интерфейс конечной точки, так и классы реализации. WSDL генерируется из классов при публикации веб-службы.
Давайте создадим веб-сервис, который будет выполнять простые операции CRUD с данными Employee .
6.1. Модельный класс
Модель Employee :
public class Employee {
private int id;
private String firstName;
//standard getters and setters
}
6.2. Интерфейс конечной точки веб-службы
Интерфейс конечной точки веб-службы, который объявляет методы веб-службы:
@WebService
public interface EmployeeService {
@WebMethod
Employee getEmployee(int id);
@WebMethod
Employee updateEmployee(int id, String name);
@WebMethod
boolean deleteEmployee(int id);
@WebMethod
Employee addEmployee(int id, String name);
//...
}
Этот интерфейс определяет абстрактный контракт для веб-службы. Использованные аннотации:
**
**
-
@ WebResult используется для настройки имени элемента XML, который
представляет возвращаемое значение
6.3. Реализация веб-сервиса
Класс реализации интерфейса конечной точки веб-службы:
@WebService(endpointInterface = "com.baeldung.jaxws.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {
@Inject
private EmployeeRepository employeeRepositoryImpl;
@WebMethod
public Employee getEmployee(int id) {
return employeeRepositoryImpl.getEmployee(id);
}
@WebMethod
public Employee updateEmployee(int id, String name) {
return employeeRepositoryImpl.updateEmployee(id, name);
}
@WebMethod
public boolean deleteEmployee(int id) {
return employeeRepositoryImpl.deleteEmployee(id);
}
@WebMethod
public Employee addEmployee(int id, String name) {
return employeeRepositoryImpl.addEmployee(id, name);
}
//...
}
7. Публикация конечных точек веб-службы
Чтобы опубликовать веб-сервисы (сверху вниз и снизу вверх), нам нужно передать адрес и экземпляр реализации веб-сервиса методу publish () класса javax.xml.ws.Endpoint :
public class EmployeeServicePublisher {
public static void main(String[]args) {
Endpoint.publish(
"http://localhost:8080/employeeservicetopdown",
new EmployeeServiceTopDownImpl());
Endpoint.publish("http://localhost:8080/employeeservice",
new EmployeeServiceImpl());
}
}
Теперь мы можем запустить EmployeeServicePublisher , чтобы запустить веб-сервис. Чтобы использовать функции CDI, веб-службы могут быть развернуты в виде файла WAR на серверах приложений, таких как WildFly или GlassFish.
8. Клиент удаленного веб-сервиса
Теперь давайте создадим клиент JAX-WS для удаленного подключения к веб-службе EmployeeService .
8.1. Генерация клиентских артефактов
Чтобы сгенерировать клиентские артефакты JAX-WS, мы снова можем использовать инструмент wsimport :
wsimport -keep -p com.baeldung.jaxws.client http://localhost:8080/employeeservice?wsdl
Сгенерированный класс EmployeeService Service инкапсулирует логику для получения порта сервера, используя URL и QName__.
8.2. Подключение к веб-сервису
Клиент веб-службы использует сгенерированный EmployeeService Service__ для подключения к серверу и удаленного вызова веб-службы:
public class EmployeeServiceClient {
public static void main(String[]args) throws Exception {
URL url = new URL("http://localhost:8080/employeeservice?wsdl");
EmployeeService__Service employeeService__Service
= new EmployeeService__Service(url);
EmployeeService employeeServiceProxy
= employeeService__Service.getEmployeeServiceImplPort();
List<Employee> allEmployees
= employeeServiceProxy.getAllEmployees();
}
}
9. Заключение
Эта статья представляет собой краткое введение в веб-службы SOAP с использованием JAX-WS .
Мы использовали как восходящий, так и нисходящий подходы к созданию веб-сервисов SOAP с использованием API JAX-WS. Мы также написали клиент JAX-WS, который может удаленно подключаться к серверу и выполнять вызовы веб-службы.
Полный исходный код доступен на over на GitHub .