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, чтобы вызывать операции «приветствующего» веб-сервиса.
Удачного кодирования
Джастин