Это будет немного сложнее, если веб-сервисы не будут приняты во внимание для первоначальной архитектуры проекта. Вы можете задействовать разные типы архитектур проектов и использовать разные виды технологий. Как разработчик, вам не разрешено изменять некоторые архитектурные элементы и конфигурации, так как может быть много зависимостей.
В большинстве учебных пособий в Интернете объясняются основные принципы создания веб-службы. Некоторое время, приложение «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 .