Spring Framework обеспечивает поддержку удаленного взаимодействия для веб-сервисов через JAX-WS. Фактически, как указано в справочной документации Spring , существует три способа представления сервисов Spring POJO в качестве веб-сервисов JAX-WS :
- Предоставление веб-служб на основе сервлетов (подходит для сред Java EE 5)
- Экспорт автономных веб-сервисов (подходит при использовании встроенного в JAX-WS поставщика Sun JDK 1.6)
- Экспорт веб-сервисов с использованием поддержки Spring JAX-WS RI (аналогично автономному подходу, но на этот раз в среде сервлетов . Подходит для не Java-сред EE, таких как Tomcat , встраивая JAX-WS RI как часть веб-приложения)
Выбор одного из трех упомянутых выше подходов зависит главным образом от вашей среды выполнения. Сказав это, мы покажем вам, как настроить и предоставить простой сервис Spring, используя все вышеперечисленные подходы.
Нашей предпочтительной средой разработки является Eclipse , поэтому в качестве предварительного условия у вас должна быть установлена Eclipse с поддержкой Maven . Установка плагина Maven для Eclipse выходит за рамки данного руководства и не будет обсуждаться. Тем не менее вам понадобятся следующие компоненты:
Для этого урока мы будем использовать Eclipse Galileo, «m2eclipse» Maven Integration для Eclipse Plugin версии 0.10.0 и Spring версии 3.0.1.
Давайте начнем,
- Создать новый проект Maven, перейти к файлу? Проект? Мавен? Maven Project
- На странице мастера «Выберите имя проекта и местоположение» убедитесь, что опция «Создать простой проект (пропустить выбор архетипа») не отмечена , нажмите «Далее», чтобы продолжить со значениями по умолчанию.
- На странице мастера «Выберите архетип» выберите «Индексатор Nexus» в раскрывающемся списке «Каталог», а после обновления области выбора архетипов выберите архетип «webapp-javaee6» из файла org.codehaus.mojo. Архетипы «использовать. Вы можете использовать текстовое поле «фильтр», чтобы сузить результаты поиска. Нажмите «Далее», чтобы продолжить
- На странице мастера «Введите идентификатор артефакта» вы можете указать название и основной пакет вашего проекта. Мы установим переменную «Group Id» в «com.javacodegeeks», а переменную «Artifact Id» в «jaxwsspring». Вышеупомянутые выборы составляют основной пакет проекта как «com.javacodegeeks.jaxwsspring» и имя проекта как «jaxwsspring». Нажмите «Готово», чтобы выйти из мастера и создать свой проект.
Давайте вспомним несколько вещей о структуре веб-проекта Maven.
- Папка / src / main / java содержит исходные файлы для динамического содержимого приложения
- Папка / src / test / java содержит все исходные файлы для модульных тестов
- Папка / src / main / webapp содержит необходимые файлы для создания допустимого веб-приложения, например, «web.xml»
- Папка / target содержит скомпилированные и упакованные результаты
- «Pom.xml» — это файл объектной модели проекта (POM). Единственный файл, который содержит все связанные с проектом конфигурации.
Здесь следует обратить внимание на то, что мы решили использовать архетип проекта Maven, совместимый с Java EE6 . Наш выбор сделан специально для того, чтобы было легко продемонстрировать все доступные подходы, упомянутые выше. Тем не менее, вы можете следовать этому руководству и представлять свои сервисы Spring как сервисы JAX-WS, даже если вы используете другую среду (например, автономную среду сервлетов, например, Apache Tomcat или сервер приложений, совместимый с Java EE 5, например, JBoss Application Server).
Чтобы правильно использовать Spring во время выполнения, мы должны предоставить все необходимые библиотеки для веб-приложения. Откройте графический редактор вашего «pom.xml» и внесите следующие изменения:
- Найдите раздел «Свойства» на странице «Обзор» редактора POM и внесите следующие изменения:
- Создайте новое свойство с именем org.springframework.version и значением 3.0.1.RELEASE
- Идентификатор группы: org.springframework Идентификатор артефакта: spring-web Версия: $ {org.springframework.version}
Как видите, Maven декларативно управляет библиотечными зависимостями. Создается локальный репозиторий (по умолчанию в папке {user_home} /. M2), и все необходимые библиотеки загружаются и помещаются туда из общедоступных репозиториев. Кроме того, внутрибиблиотечные зависимости автоматически разрешаются и обрабатываются.
Следующим шагом является предоставление хуков для веб-приложения для загрузки контекста Spring при запуске.
Создайте файл «WEB-INF /web.xml» в папке / src / main / webapp и добавьте следующее:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<?xml version="1.0" encoding="UTF-8"?> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>jaxwsspring</display-name> <session-config> <session-timeout>30</session-timeout> </session-config> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list></web-app> |
Теперь давайте создадим файл applicationContext.xml, который будет управлять контейнером Spring . Создайте файл в каталоге / src / main / webapp / WEB-INF. Пример «applicationContext.xml» представлен ниже:
Что следует отметить здесь:
- Измените атрибут base-package элемента context: component-scan на тот, который является базовым пакетом вашего проекта, чтобы проверять его на наличие компонентов Spring.
Теперь давайте создадим «приветственный» сервис Spring . Создайте подпакет с именем «services» в вашем основном пакете и поместите туда класс «GreetingService». Пример услуги «приветствие» показан ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
package com.javacodegeeks.jaxwsspring.services;import org.springframework.stereotype.Service;@Service("greetingService")public class GreetingService { public String sayHello() { return "Hello from Greeting Service"; } } |
JAX – WS требует работы с выделенными классами конечных точек. Если необходимо экспортировать существующий сервис, класс-оболочка является самым простым JAX-WS- совместимым способом. Давайте теперь создадим класс приветствия для конечной точки. Создайте подпакет с именем «конечные точки» под вашим основным пакетом и поместите туда класс «GreetingServiceEndpoint». Пример класса приветствия конечной точки показан ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.javacodegeeks.jaxwsspring.endpoints;import javax.jws.WebMethod;import javax.jws.WebService;import org.springframework.beans.factory.annotation.Autowired;import com.javacodegeeks.jaxwsspring.services.GreetingService;@WebService(serviceName="GreetingService")public class GreetingServiceEndpoint { @Autowired private GreetingService greetingService; @WebMethod public String sayHello() { return greetingService.sayHello(); } } |
Как вы можете видеть, это реализация JAX-WS- службы «приветствия», которая просто делегирует реализацию «GreetingService». Это класс, который будет зарегистрирован в движке JAX – WS . В случае сервера Java EE 5 (подход веб-служб на основе сервлетов ) механизм веб-служб управляет жизненным циклом экземпляров класса конечной точки. В двух других случаях экземпляры конечных точек определяются и управляются как сами бины Spring, поэтому их жизненный цикл будет соответствовать контексту приложения Spring .
Spring предоставляет удобный базовый класс для реализаций конечной точки сервлета JAX – WS — «SpringBeanAutowiringSupport». Чтобы представить наш «GreetingService» как веб-сервис на основе сервлетов, мы должны действовать следующим образом:
- Измените наш класс «GreetingServiceEndpoint», чтобы расширить класс SpringBeanAutowiringSupport в Spring. Таким образом, аннотация @Autowired будет принята , и контейнер IoC Spring сможет внедрить фактический экземпляр «приветствия» в класс конечной точки для правильного делегирования вызовов.
- Наш «GreetingServiceEndpoint» должен запускаться в том же веб-приложении, что и контекст Spring, чтобы обеспечить доступ к возможностям Spring. Это случай по умолчанию в средах Java EE 5, использующих стандартный контракт для развертывания конечной точки сервлета JAX-WS .
- Конечная точка — это класс, зарегистрированный в реализации JAX-WS на стороне сервера. В случае сервера Java EE 5 это будет просто определено как сервлет в «web.xml», при этом сервер обнаружит, что это конечная точка JAX-WS, и отреагирует соответствующим образом. Имя сервлета обычно должно соответствовать указанному имени веб-службы.
Имея это в виду, измените класс конечной точки, как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.javacodegeeks.jaxwsspring.endpoints;import javax.jws.WebMethod;import javax.jws.WebService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.context.support.SpringBeanAutowiringSupport;import com.javacodegeeks.jaxwsspring.services.GreetingService;@WebService(serviceName="GreetingService")public class GreetingServiceEndpoint extends SpringBeanAutowiringSupport { @Autowired private GreetingService greetingService; @WebMethod public String sayHello() { return greetingService.sayHello(); } } |
Наконец добавьте в ваш «web.xml» следующее объявление сервлета :
|
01
02
03
04
05
06
07
08
09
10
11
|
<servlet> <servlet-name>GreetingService</servlet-name> <servlet-class> com.javacodegeeks.jaxwsspring.endpoints.GreetingServiceEndpoint </servlet-class> </servlet> <servlet-mapping> <servlet-name>GreetingService</servlet-name> <url-pattern>/GreetingService</url-pattern> </servlet-mapping> |
Чтобы создать приложение, щелкните правой кнопкой мыши на вашем проекте? Беги как ? Maven пакет
Чтобы развернуть веб-приложение, просто скопируйте файл «.war» из каталога «target» на сервер Java EE 5, в папку развертывания веб-приложения. Для целей данного руководства мы собираемся развернуть наше веб-приложение на сервере приложений JBoss 5.1.0.
Чтобы запустить приложение, укажите ваш браузер по следующему адресу
HTTP: // локальный: 8080 / jaxwsspring /
Если все прошло хорошо, вы должны увидеть на своей главной веб-странице следующее:
«Привет мир!»
Адрес нашей веб-службы должен быть по адресу:
HTTP: // локальный: 8080 / jaxwsspring / GreetingService
Мы можем просмотреть наш веб-сервис WSDL, если мы укажем нашему браузеру:
HTTP: // локальный: 8080 / jaxwsspring / GreetingService WSDL
Результат должен быть примерно таким:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<definitions name="GreetingService" targetNamespace="http://endpoints.jaxwsspring.javacodegeeks.com/"> <types> <xs:element name="sayHello" type="tns:sayHello"/> <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/> <xs:complexType name="sayHello"> <xs:sequence/> </xs:complexType> <xs:complexType name="sayHelloResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </types> <message name="GreetingServiceEndpoint_sayHello"> <part element="tns:sayHello" name="sayHello"/> </message> <message name="GreetingServiceEndpoint_sayHelloResponse"> <part element="tns:sayHelloResponse" name="sayHelloResponse"/> </message> <portType name="GreetingServiceEndpoint"> <operation name="sayHello" parameterOrder="sayHello"> <input message="tns:GreetingServiceEndpoint_sayHello"/> <output message="tns:GreetingServiceEndpoint_sayHelloResponse"/> </operation> </portType> <binding name="GreetingServiceEndpointBinding" type="tns:GreetingServiceEndpoint"> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="GreetingService"> <port binding="tns:GreetingServiceEndpointBinding" name="GreetingServiceEndpointPort"> </port> </service></definitions> |
Теперь, когда у нас есть определение веб-службы, мы можем использовать наш любимый клиент SOAP — генерировать или реализовать его — для вызова операций «приветствующего» веб-службы. Доступ к веб-сервису выходит за рамки данного руководства, поэтому мы не будем его обсуждать. Тем не менее, мы собираемся предоставить пример диалогового окна «запрос — ответ» при вызове операции «sayHello» «GreetingService» с использованием нашего предпочтительного инструмента для тестирования веб-служб, soapUI
Запрос SOAP, отправленный инструментом soapUI:
|
1
2
3
4
5
6
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:end="http://endpoints.jaxwsspring.javacodegeeks.com/"> <soapenv:Header/> <soapenv:Body> <end:sayHello/> </soapenv:Body></soapenv:Envelope> |
Соответствующий ответ SOAP, полученный от «приветствующего» веб-сервиса:
|
1
2
3
4
5
6
7
8
|
<env:Header/> <env:Body> <return>Hello from Greeting Service</return> </ns2:sayHelloResponse> </env:Body></env:Envelope> |
Как указывалось выше, встроенный поставщик JAX-WS , поставляемый с Sun JDK 1.6, поддерживает доступ к веб-службам с помощью встроенного HTTP-сервера, который также включен в JDK 1.6. SimpleJaxWsServiceExporter Spring обнаруживает все аннотированные bean-компоненты @WebService в контексте приложения Spring , экспортируя их через сервер JAX-WS по умолчанию (HTTP-сервер JDK 1.6).
В этом сценарии экземпляры конечных точек определяются и управляются как сами бины Spring ; они будут зарегистрированы в движке JAX-WS, но их жизненный цикл будет соответствовать контексту приложения Spring . Это означает, что функциональность Spring, такая как явное внедрение зависимостей, может применяться к экземплярам конечной точки. Конечно, инъекция, основанная на аннотациях через @Autowired, также будет работать.
Чтобы использовать этот подход, все что нам нужно сделать, это объявить наш класс конечной точки как bean-компонент Spring , аннотируя его аннотацией @Service . Кроме того, мы должны добавить объявление bean-компонента «SimpleJaxWsServiceExporter» в файл контекста нашего приложения, как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.javacodegeeks.jaxwsspring.endpoints;import javax.jws.WebMethod;import javax.jws.WebService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.javacodegeeks.jaxwsspring.services.GreetingService;@Service("greetingServiceEndpoint")@WebService(serviceName="GreetingService")public class GreetingServiceEndpoint { @Autowired private GreetingService greetingService; @WebMethod public String sayHello() { return greetingService.sayHello(); } } |
Что следует отметить здесь:
- GreetingServiceEndpoint может быть производным от SpringBeanAutowiringSupport, но не обязательным, так как конечная точка здесь полностью управляется Spring.
Что следует отметить здесь:
- Измените атрибут base-package элемента context: component-scan на тот, который является базовым пакетом вашего проекта, чтобы проверять его на наличие компонентов Spring.
- Вы можете изменить свойство «baseAddress» «SimpleJaxWsServiceExporter» в соответствии с вашими потребностями. «BaseAddress» — это адрес, по которому будут экспортироваться все обнаруженные веб-сервисы. По умолчанию «baseAddress» — «http: // localhost: 8080 /»
Чтобы создать приложение, щелкните правой кнопкой мыши на вашем проекте? Беги как ? Maven пакет
Чтобы проверить конкретный подход, мы собираемся развернуть наше веб-приложение на сервере Apache Tomcat 6. Не забывайте, что мы будем использовать встроенный в JAX-WS поставщик Sun JDK 1.6; даже если мы работаем в контейнере сервлетов . В этом конкретном сценарии мы используем контейнер сервлетов только для запуска приложения Spring . В качестве альтернативы вы можете реализовать класс Main и запустить приложение Spring программно.
Чтобы запустить приложение, укажите ваш браузер по следующему адресу
HTTP: // локальный: 8080 / jaxwsspring /
Если все прошло хорошо, вы должны увидеть на своей главной веб-странице следующее:
«Привет мир!»
Адрес нашей веб-службы должен быть по адресу:
HTTP: // локальный: 9999 / GreetingService
Мы можем просмотреть наш веб-сервис WSDL, если мы укажем нашему браузеру:
HTTP: // локальный: 9999 / GreetingService WSDL
Еще раз мы можем использовать определение веб-сервиса для генерации и / или реализации клиента SOAP, чтобы вызывать операции «приветствующего» веб-сервиса.
Sun JAX-WS RI, разработанный в рамках проекта GlassFish, поставляет поддержку Spring в рамках проекта JAX-WS Commons. Это позволяет определять конечные точки JAX-WS как bean-компоненты, управляемые Spring, аналогично автономному режиму, описанному в предыдущем разделе, но на этот раз в среде сервлетов . Обратите внимание, что это не переносимо в среде Java EE 5; он в основном предназначен для не-EE-сред, таких как Tomcat , встраивая JAX-WS RI как часть веб-приложения.
Отличие от стандартного стиля экспорта конечных точек на основе сервлетов заключается в том, что Spring будет управлять жизненным циклом самих экземпляров конечных точек и что в «web.xml» будет определен только один сервлет JAX-WS . Со стандартным стилем Java EE 5 (как показано выше) у вас будет одно определение сервлета на конечную точку службы, причем каждая конечная точка обычно делегируется бинам Spring .
Этот последний подход специфичен для Spring 2.0 , поэтому перед изменением любого нашего кода мы должны немного изменить конфигурацию нашего проекта. В частности, мы должны удалить зависимость для библиотек Spring 3 и добавить новую в библиотеку jaxws-spring . Откройте графический редактор вашего «pom.xml» и внесите следующие изменения:
- Найдите раздел «Свойства» на странице «Обзор» редактора POM и удалите свойство с именем org.springframework.version, если оно существует — если вы следовали этому руководству с самого начала
- Перейдите на страницу «Зависимости» редактора POM и создайте следующие зависимости (вы должны заполнить поля «GroupId», «Artifact Id» и «Version» в разделе «Dependency Details» на этой странице):
- Идентификатор группы: org.jvnet.jax-ws-commons.spring Идентификатор артефакта: jaxws-spring Версия: 1.8
- Идентификатор группы: com.sun.xml.bind Идентификатор артефакта: jaxb-impl
- Идентификатор группы: com.sun.xml.bind Идентификатор артефакта: jaxb-impl Версия: 2.1.6
- Id: download.java.net репо 1 URL: http://download.java.net/maven/1/ Макет: наследие
- Id: download.java.net URL репо 2 URL: http://download.java.net/maven/2/
Чтобы использовать этот подход, мы должны выполнить шаги, описанные ниже:
Найдите файл «web.xml» и измените его, определив основной сервлет JAX-WS, а также столько отображений сервлета, сколько необходимо для сервисов, которые мы хотим представить как веб-сервисы; одно отображение сервлета на сервис. Таким образом, для нашего конкретного тестового примера мы должны добавить следующие объявления:
|
1
2
3
4
5
6
7
8
9
|
<servlet> <servlet-name>jaxws-servlet</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>jaxws-servlet</servlet-name> <url-pattern>/GreetingService</url-pattern> </servlet-mapping> |
Измените файл «applicationContext.xml», как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
xsi:schemaLocation=" <wss:binding url="/GreetingService"> <wss:service> <ws:service bean="#greetingService" /> </wss:service> </wss:binding> <bean id="greetingService" class="com.javacodegeeks.jaxwsspring.services.GreetingService" /></beans> |
Что следует отметить здесь:
- Этот подход специфичен для Spring 2.0 , поэтому был создан файл applicationContext.xml, совместимый с Spring 2.0 . Обратите внимание, что мы объявили bean-компонент Spring службы приветствия непосредственно в файле applicationContext.xml, поскольку аннотация @Service недоступна в Spring 2.0.
- Определение wss: binding определяет, какой сервис открыт для какой части пространства URL. В приведенном выше коде он развертывает «GreetingService» по URL-адресу / GreetingService
- Определение ws: service реализует экземпляр веб-службы. В самом простом виде атрибут bean-компонента должен быть настроен для делегирования всех вызовов назначенному бобу Spring . Как вы можете видеть с этим подходом, мы можем опустить создание класса «конечной точки» для прокси наших сервисов Spring .
Наконец, мы реализуем наш «GreetingService», как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package com.javacodegeeks.jaxwsspring.services;import javax.jws.WebMethod;import javax.jws.WebService;import javax.jws.soap.SOAPBinding;import javax.jws.soap.SOAPBinding.Style;import javax.jws.soap.SOAPBinding.Use;@WebService(serviceName="GreetingService")@SOAPBinding(style = Style.RPC, use = Use.LITERAL)public class GreetingService { @WebMethod public String sayHello() { return "Hello from Greeting Service"; } } |
Что следует отметить здесь:
- Вам следует запустить инструмент « wsgen », если вы используете « Style.DOCUMENT ». « Style.RPC » используется только в демонстрационных целях.
- Аннотация @Service недоступна в Spring 2.0, поэтому мы объявляем ее непосредственно в файле applicationContext.xml.
Чтобы создать приложение, щелкните правой кнопкой мыши на вашем проекте? Беги как ? Maven пакет
Чтобы проверить конкретный подход, мы собираемся развернуть наше веб-приложение на сервере Apache Tomcat 6.
Чтобы запустить приложение, укажите ваш браузер по следующему адресу
HTTP: // локальный: 8080 / jaxwsspring /
Если все прошло хорошо, вы должны увидеть на своей главной веб-странице следующее:
«Привет мир!»
Адрес нашей веб-службы должен быть по адресу:
HTTP: // локальный: 8080 / jaxwsspring / GreetingService
Мы можем просмотреть наш веб-сервис WSDL, если мы укажем нашему браузеру:
HTTP: // локальный: 8080 / jaxwsspring / GreetingService WSDL
Еще раз мы можем использовать определение веб-сервиса для генерации и / или реализации клиента SOAP, чтобы вызывать операции «приветствующего» веб-сервиса.
Удачного кодирования
Джастин