Это будет немного сложнее, если веб-сервисы не будут приняты во внимание для первоначальной архитектуры проекта. Вы можете задействовать разные типы архитектур проектов и использовать разные виды технологий. Как разработчик, вам не разрешено изменять некоторые архитектурные элементы и конфигурации, так как может быть много зависимостей.
В большинстве учебных пособий в Интернете объясняются основные принципы создания веб-службы. Некоторое время, приложение «Hello world» или когда-нибудь это может быть простой калькулятор, как это. Эти учебные пособия полезны для понимания основ веб-сервисов. Но сценарии реального мира сложнее, чем десять, и им приходится сталкиваться с трудностями при следовании подобным учебным пособиям.
Практический сценарий
В этом уроке я собираюсь объяснить, как мы на самом деле выполняем требования реального мира, предъявляемые вашим руководителем. Я собираюсь объяснить тот же сценарий, с которым я столкнулся недавно.
Организация здравоохранения управляет множеством аптек по всему острову. У них есть веб-приложение, которое обрабатывает все запасы, цены и счета, выдачу аптечных товаров и т. Д. Им нужно было выставлять цены на свои аптечные товары через веб-сервис, чтобы их клиентское приложение в аптеке могло получить доступ к ним через веб-сервис.
Их веб-приложение было разработано в интегрированной среде Struts2, Spring и Hibernated. Здесь есть все классы DAO, а также классы обслуживания. Приложение использует технику автоматического подключения Spring, сканирование компонентов, управление транзакциями и т. Д. В связи с этим я должен был представить цены на товары аптек в виде веб-службы. Это означает, что некоторые методы нашей текущей аптечной службы должны быть доступны для внешних пользователей через веб-службу.
Я покажу вам, как достичь такого рода требований с минимальными изменениями в нашем существующем проекте.
Дополнительные библиотеки
Я собираюсь реализовать веб-сервис с JAX-WS . Я использовал JAX-WS 2.2 для своего проекта. Вы можете скачать необходимую версию JAX-WS здесь . Это обеспечивает несколько инструментов, которые можно использовать для создания веб-сервиса и его клиентского материала. Загрузив нужную версию библиотеки, распакуйте ее где-нибудь на вашем локальном компьютере. Я поместил это в мою домашнюю папку.
то есть: /home/semika/jaxws-ri-2.2
Реализация веб-сервиса
У меня уже есть классы обслуживания с пружинным управлением и классы DAO для аптек, которые внутренне используются веб-приложением. Те не выставлены наружу. Предположим, нам нужно предоставить метод findAll (), который возвращает список «PharmacyItem» интерфейса «PharmacyService» в виде веб-службы.
Для вашего удобства я покажу вам Java-класс «PharmacyServiceImpl», который используется для выполнения обычных операций с аптекой. Это обычный весенний фасоль. Помните, что методы этого класса в настоящее время могут использоваться только для внутренних операций нашего веб-приложения. Они не выставляются как веб-сервисы.
PharmacyServiceImpl.java
|
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
|
/** * */package com.slauto.service.pharmacy.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.slauto.exceptions.ServiceException;import com.slauto.model.pharmacy.PharmacyItem;import com.slauto.persist.pharmacy.api.PharmacyItemDao;import com.slauto.service.pharmacy.api.PharmacyItemService;/** * @author semika * */@Service('pharmacyItemService') public class PharmacyItemServiceImpl implements PharmacyItemService { @Autowired private PharmacyItemDao pharmacyItemDao; @Override public List<Pharmacyitem> findAll() throws ServiceException { return pharmacyItemDao.findAllPharmacyItems(); }} |
Как видите, у меня есть автоматически подключенный экземпляр PharmacyItemDao в классе реализации. Как мы все знаем, это класс реализации управляемых пружин.
Далее мы реализуем класс конечных точек веб-службы для вышеуказанного bean-компонента, управляемого управляемой службой, чтобы представить его методы как методы веб-службы. Для ясности я создал отдельный класс в качестве конечной точки веб-службы.
PharmacyItemServiceEndPoint.java
|
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
|
package com.slauto.service.ws;import javax.jws.WebMethod;import javax.jws.WebService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.slauto.exceptions.DataAccessException;import com.slauto.model.pharmacy.PharmacyItem;import com.slauto.service.pharmacy.api.PharmacyItemService;/** * @author semika * */@WebService(serviceName='pharmacyItemService') public class PharmacyItemServiceEndPoint { @WebMethod public List<Pharmacyitem> findAll() throws DataAccessException { ApplicationContext context = new ClassPathXmlApplicationContext('applicationContext.xml'); PharmacyItemService pharmacyItemService = (PharmacyItemService)context.getBean('pharmacyItemService'); return pharmacyItemService.findAll(); }} |
Как вы можете видеть здесь, я использую компонент «pharmacyItemService», который используется нашим веб-приложением для доступа к соответствующему методу обслуживания. PharmacyItemService — это обычный боб весеннего чеснока, который используется для выполнения повседневных операций аптеки. Ничего особенного в этом нет. Особо отметим, что аннотации @WebService и @WebMethod, указывающие, что этот класс работает как конечная точка веб-службы.
Здесь я получаю экземпляр класса обслуживания через контекст приложения. Кроме того, мы можем автоматически связывать классы конечных точек веб-службы с пружиной, расширяя классы конечных точек из SpringBeanAutowiringSupport , предоставляемого spring. В этом случае нам не нужно создавать экземпляр контекста приложения, как я делал выше. Я не мог сделать эту работу, поэтому я использовал вышеописанную технику.
При использовании SpringBeanAutowiringSupport при развертывании веб-службы (поясните ниже) я обнаружил исключение, которое мне было трудно разрешить. Поэтому я выбираю эту технику. В любом случае, мне не нравится то, что я использовал выше :).
Создание веб-сервиса
Я использую инструменты apt , wsgen и wsimport , предоставляемые JAX-WS, для генерации переносимых артефактов, используемых в сервисах JAX-WS. Соответствующие цели муравья для файла build.xml будут следующими.
Возможно, вам понадобится следующее свойство, объявленное в верхней части файла build.xml.
Имущество:
|
1
2
3
4
|
<property name='tomcat.home' value='/home/semika/apache-tomcat-7.0.25' /><property name='jaxws.home' value='/home/semika/jaxws-ri-2.2' /><property name='build.classes.home' value='${basedir}/WEB-INF/classes' /><property name='java.home' value='/home/semika/java/jdk1.6.0_30'> |
Путь к классу:
|
1
2
3
4
5
6
7
8
|
<path id='project.class.path'> <pathelement location='${java.home}/../lib/tools.jar' /> <fileset dir='${jaxws.home}/lib'> <include name='*.jar' /> </fileset> <pathelement location='${basedir}/WEB-INF/classes' /> <fileset dir='${basedir}/WEB-INF/lib' includes='*.jar' /></path> |
Цель инструмента JAX-WS apt:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
<target name='apt' depends='javac'> <taskdef name='apt' classname='com.sun.tools.ws.ant.Apt'> <classpath refid='project.class.path' /> </taskdef> <apt fork='true' debug='true' verbose='true' destdir='${basedir}/WEB-INF/classes' sourcedestdir='${basedir}/WEB-INF/src' sourcepath='${basedir}/WEB-INF/src'> <classpath> <path refid='project.class.path' /> </classpath> <option key='r' value='${basedir}/WEB-INF' /> <source dir='${basedir}/WEB-INF/src'> <include name='**/*.java'/> </source> </apt></target> |
Если вы хотите узнать больше об инструменте apt, предоставляемом JAX-WS, посмотрите на это . При запуске apt target он сканирует исходный путь (папка src) и генерирует необходимые файлы * .class и * .java для классов, помеченных @WebService. В этом случае для «PharmacyItemServiceEndPoint.java». Если вы посмотрите на пакет, в котором находится «PharmacyItemServiceEndPoint», то увидите, что для него создан новый пакет « jaxws ». Внутри этого пакета я мог видеть следующие три файла Java.
DataAccessExceptionBean.java
FindAll.java
FindAllResponse.java
Эти классы генерируются инструментом, и они различаются в зависимости от реализации вашего сервиса и зависимых классов, которые вы задействуете в своем веб-сервисе. На самом деле, вам не нужно сильно беспокоиться об этих сгенерированных вещах.
Аналогично, вы можете увидеть соответствующие файлы * .class в папке / WEB-INF / classes.
JAX-WS wsgen tool target:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<target name='wsgen' depends='apt'> <taskdef name='wsgen' classname='com.sun.tools.ws.ant.WsGen'> <classpath path='project.class.path'/> </taskdef> <wsgen xendorsed='true' sei='com.slauto.service.ws.PharmacyItemServiceEndPoint' destdir='${basedir}/WEB-INF/classes' resourcedestdir='${wsdl.dir}' sourcedestdir='${basedir}/WEB-INF/src' keep='true' verbose='true' genwsdl='true'> <classpath refid='project.class.path'/> </wsgen></target> |
Инструмент wsgen сгенерирует файл WSDL для нашего класса веб-службы конечной точки. После запуска этой цели посмотрите на местоположение $ {wsdl.dir}. Вы можете видеть, что наш файл WSDL был создан. Если вы хотите узнать больше об инструменте wsgen, предоставляемом JAX-WS, посмотрите на это .
Развертывание веб-службы
Я хотел развернуть веб-сервис с обычным запуском сервера. Поэтому мне пришлось добавить следующую конфигурацию в файл web.xml .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<listener> <listener-class> com.sun.xml.ws.transport.http.servlet.WSServletContextListener </listener-class></listener><servlet> <servlet-name>pharmacyItemService</servlet-name> <servlet-class> com.sun.xml.ws.transport.http.servlet.WSServlet </servlet-class> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>pharmacyItemService</servlet-name> <url-pattern>/pharmacyItemService</url-pattern></servlet-mapping> |
Как я уже говорил, при развертывании веб-службы с классом конечной точки, расширенным из SpringBeanAutowiringSupport , это дает исключение. Вот почему я решил получить компонент сервиса через контекст приложения. Если вам удастся справиться с этой ситуацией, просто оставьте сообщение.
А также вам необходимо создать файл sun-jaxws.xml в папке WEB-INF и объявить конечную точку веб-службы следующим образом.
|
1
2
3
4
5
6
7
|
<?xml version='1.0' encoding='UTF-8'?> <endpoint name='pharmacyItemService' implementation='com.slauto.service.ws.PharmacyItemServiceEndPoint' url-pattern='/pharmacyItemService'/></endpoints> |
Я использую Apache Tomcat 7.0.25 для развертывания веб-службы. Вам нужно будет сообщить tomcat, где он может найти библиотеки JAX-WS при запуске tomcat. Вы можете редактировать файл ‘ catalina.properties ‘, расположенный в папке CATALINA_HOME / conf. Найдите свойство common.loader . В основном это будет выглядеть следующим образом.
|
1
|
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar |
Измените его следующим образом.
|
1
|
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,/home/semika/jaxws-ri-2.2/lib/*.jar |
Как видите, я добавил свой путь к библиотеке JAX-WS в конце списка, разделенного запятыми. Эти классы доступны как внутренним классам tomcat, так и всем веб-приложениям, развернутым в контейнере tomcat. Теперь вы можете скопировать ваш .war- файл в папку webapps на tomcat и запустить tomcat. Ваш веб-сервис должен быть развернут. Чтобы убедиться, что ваш веб-сервис развернут правильно, вы можете проверить его WSDL . Для файла WSDL, вы должны проверить URL в следующем формате.
http: // localhost: 8080 / <имя вашего контекста> / pharmacyItemService? wsdl
Если Вы можете увидеть свой файл WSDL в браузере, Вы закончили, Вы успешно развернули веб-сервис.
Создание клиента веб-сервиса
Теперь у нас есть развернутый веб-сервис. Далее мы увидим, как написать клиентский класс для доступа к веб-сервису с помощью Java-программы. Вы можете создать простой проект Java и использовать следующий файл build.xml . Я разместил полный файл build.xml для генерации клиента. Я использую инструмент wsimport, поставляемый с JAX-WS, для генерации артефактов клиента веб-сервиса.
|
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
|
<?xml version='1.0' encoding='utf-8' ?><project name='WS-client' default='wsimport' basedir='.'> <property name='jaxws.home' value='/home/semika/jaxws-ri-2.2' /> <property name='java.home' value='/home/semika/java/jdk1.6.0_30'/> <path id='jaxws.classpath'> <pathelement location='${java.home}/../lib/tools.jar' /> <fileset dir='${jaxws.home}/lib'> <include name='*.jar' /> </fileset> </path> <target name='wsimport'> <taskdef name='wsimport' classname='com.sun.tools.ws.ant.WsImport'> <classpath path='jaxws.classpath'/> </taskdef> <wsimport xendorsed='true' debug='true' verbose='true' keep='true' destdir='src' package='com.slauto.service' </wsimport> </target></project> |
Если вы хотите узнать больше об инструменте wsimport, вы можете посмотреть на это . После запуска вышеуказанной цели просто взгляните на пакет, который вы указали в атрибутах wsimport. Вы увидите набор сгенерированных файлов Java. Вы можете скомпилировать и связать их в один файл client.jar и использовать с любым проектом java, который нуждается в этом веб-сервисе.
Я создал очень простой Java-класс для получения информации об аптеках через веб-сервис.
Client.java
|
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
|
package com.slauto.client;import java.util.List;import com.slauto.service.PharmacyItem;import com.slauto.service.PharmacyItemService;import com.slauto.service.PharmacyItemServiceEndPoint;/** * @author semika * */public class Client { /** * @param args */ public static void main(String[] args) { PharmacyItemService p = new PharmacyItemService(); PharmacyItemServiceEndPoint ep = p.getPharmacyItemServiceEndPointPort(); List<PharmacyItem> pharmacyItems = ep.findAll(); for (PharmacyItem pharmacyItem : pharmacyItems) { System.out.println(pharmacyItem.getCode()); } } } |
Это прекрасно, не правда ли? Вы увидите список кодов аптек, отображаемый сразу после запуска этого класса. Эта аптечная информация поступает через веб-сервис, развернутый веб-приложением, разработанным в сильно сложной среде.
Вот и все из этого урока. Я надеюсь, что это будет полезно для вас, и если вы что-то узнаете из этого урока, не забудьте оставить комментарий.
Справка: Как представить существующий сервис в качестве веб-сервиса? от нашего партнера JCG Семика локу калуге в блоге Code Box .