Статьи

Давайте напишем документ в стиле веб-сервиса

Возможно, вы знаете, что в основном мы можем использовать четыре различных стиля веб-сервисов. Они заключаются в следующем:

  • Документ / Буквенный
  • Документ / буквенное завернутый
  • RPC / Закодированного
  • RPC / Буквальный

Конечно, стиль RPC / Encoded теперь устарел. Если вам интересно, вы можете прочитать о различных стилях веб-сервисов и их плюсах и минусах в этой очень всеобъемлющей статье, найденной здесь .

Сегодня мы увидим, как написать оболочку Document / Literal для веб-службы. Повестка дня этого поста следующая:

  • Написать простой веб-сервис на основе Document / Literal
  • Как разместить простой веб-сервис в веб-контейнере Tomcat
  • Простой тестовый клиент для тестирования нашего сервиса

Итак, давайте начнем наше путешествие:

  • Написать простой веб-сервис на основе Document / Literal
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package com.wsbindings;
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
 
@WebService
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL, parameterStyle = ParameterStyle.WRAPPED)
public interface AddService {
 
    @WebMethod
    public int addIntegers(@WebParam(name = "intOne") int paramOne,
            @WebParam(name = "intTwo") int paramTwo);
}

Так что это наш основной веб-сервис. Это наш базовый интерфейс для нашего сервиса. Как вы можете видеть, мы сначала аннотируем его с помощью @ javax.jws.WebService, чтобы указать, что это веб-сервис, который мы собираемся написать. Затем следует интересная часть, где мы определяем нашу SOAPBinding . Здесь мы заявляем, что хотим написать веб-сервис в стиле DOCUMENT, который является LITERAL и WRAPPED. Здесь следует обратить внимание на то, что все три значения атрибута, указанные в аннотации Soap Binding, являются значениями по умолчанию, поэтому вы можете обойтись без объявления их здесь явно. Я сделал это для ясности этой статьи.

Продолжим, давайте посмотрим, как будет выглядеть реализация для этого конкретного интерфейса:

01
02
03
04
05
06
07
08
09
10
11
12
package com.wsbindings;
 
import javax.jws.WebService;
 
@WebService(endpointInterface="com.wsbindings.AddService")
public class AddServiceImpl implements AddService{
 
    public int addIntegers(int paramOne, int paramTwo) {
        return paramOne+paramTwo;
    }
 
}

Опять же, ничего особенного в том, что делает этот сервис. Просто добавьте два переданных числа и отправьте обратно результат сложения. Обратите внимание, что и здесь мы должны аннотировать класс реализации аннотацией @WebService . Теперь, когда мы завершили начальную часть написания нашего контракта на веб-сервис и реализацию, давайте посмотрим, как мы можем разместить его в веб-контейнере tomcat.

  • Как разместить простой веб-сервис в веб-контейнере Tomcat

Как вы знаете, по умолчанию tomcat не поставляется с реализацией JAX-WS в отличие от типичных серверов приложений, таких как JBoss, Glassfish. Следовательно, чтобы это работало, вам нужно получить реализацию спецификации JAX-WS. В этом случае мы будем использовать Metro . Вы можете скопировать jar-файлы из загружаемого файла в свой каталог WEB-INF / lib или использовать Maven, чтобы сделать это за вас, что я и буду делать в этой статье. Поэтому, чтобы получить требуемые jar-файлы, относящиеся к реализации Metro, я добавляю следующую зависимость в мой pom:

01
02
03
04
05
06
07
08
09
10
11
12
<dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.1.3</version>
        <exclusions>
            <exclusion>
                <groupId>com.sun.xml.stream</groupId>
                <artifactId>sjsxp</artifactId>
 
            </exclusion>
        </exclusions>
    </dependency>

Обратите внимание, что я добавил одно исключение для артефакта sjsxp, так как мне нужна была более новая версия, чем та, которая была разработана из транзитивной зависимости. Потому что иначе вы получите следующее исключение.

Не удалось инициализировать класс javax.xml.stream.XMLStreamException: базовая кодировка потока UTF-8 и входной параметр для метода writeStartDocument () utf-8 не совпадают.

Чтобы преодолеть эту проблему, мне нужно было добавить следующую зависимость в мой pom:

1
2
3
4
5
<dependency>
        <groupId>com.sun.xml.stream</groupId>
        <artifactId>sjsxp</artifactId>
        <version>1.0.1</version>
    </dependency>

Я смог найти это решение благодаря этой теме.

Двигаясь дальше, нам нужно определить конкретный XML-файл, который должен находиться в каталоге WEB-INF с именем sun-jaxws.xml . Этот XML определяет, как мы можем получить доступ к нашим веб-сервисам и где находится класс имплментации. Давайте посмотрим на содержимое этого файла:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
  <endpoint
     name="AddWS"
     implementation="com.wsbindings.AddServiceImpl"
     url-pattern="/addws"/>
</endpoints>

Здесь мы даем пакет, в котором находится класс реализации нашего веб-сервиса, а также шаблон URL для доступа к конкретному веб-сервису. И последнее, что мы должны сделать, это добавить следующее в наш 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>AddWS</servlet-name>
        <servlet-class>
            com.sun.xml.ws.transport.http.servlet.WSServlet
        </servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>AddWS</servlet-name>
        <url-pattern>/addws</url-pattern>
    </servlet-mapping>

Обратите внимание, что мы должны определить прослушиватель контекста и класс сервлета, который будет обрабатывать наши вызовы веб-службы. Если вы посмотрите на источник WSServletContextListner, то увидите, что он читает файл sun-jaxws.xml из каталога WEB-INF и создает загрузчики классов соответственно для контекста веб-службы. Одна вещь о веб-сервисах стиля документа состоит в том, что вам нужно сгенерировать некоторый код для запроса и ответа. Если вы этого не сделаете, вы получите следующую ошибку со следующим сообщением:

Вы запускали APT для их генерации?

Вы можете сгенерировать необходимые классы, используя инструмент wsgen, который поставляется вместе с вашей установкой JDK. Вы также можете использовать Apache-CXF для генерации этих классов для вас. Мы будем использовать последний подход, используя плагин apache-cxf maven, который доступен для нас. Включите следующее в ваш pom и ваш ход;

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
<plugin>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>2.0.9</version>
            <dependencies>
                <dependency>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-frontend-jaxws</artifactId>
                    <version>2.0.9</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <id>generate-wsdl</id>
                    <phase>process-classes</phase>
                    <configuration>
                        <className>com.wsbindings.AddServiceImpl</className>
                        <argline>-classdir ${project.build.directory}/classes</argline>
 
                    </configuration>
 
                    <goals>
                        <goal>java2wsdl</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Здесь мы используем команду java2wsdl для создания необходимых объектов запросов и ответов для нашего веб-сервиса. Как вы можете видеть, я использовал атрибут <argline>, чтобы указать, куда я хочу, чтобы мои сгенерированные классы шли. Так как обычная задача компиляции maven, которая запускается при сборке файла war, будет выглядеть в каталоге классов, я указал, что наши классы также должны быть включены в тот же путь, чтобы они были связаны вместе с нашим классом веб-сервисов, когда война создано. Вы можете просмотреть все возможные команды, выполнив указанные здесь параметры.

Мой pom указывал на ошибку, когда я включил свой плагин apache-cxf maven следующим образом:
Выполнение плагина не охватывается конфигурацией жизненного цикла
и после некоторого исследования проблемы я наткнулся на решение, как указано здесь. Чтобы решить эту проблему, вы должны включить следующий фрагмент под тегом <build> вашего pom:

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
     
<pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>org.apache.cxf</groupId>
                                        <artifactId>cxf-codegen-plugin</artifactId>
                                        <version>2.0.9</version>
                                        <goals>
                                            <goal>test-compile</goal>
                                            <goal>compile</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <execute />
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

Это должно избавить вас от этой ошибки, хотя я не могу дать вам точную причину, почему появляется это предупреждение. Если кто-то из вас знает точную причину, я был бы признателен, если бы вы могли оставить комментарий для всех нас. После этого вы можете просто сгенерировать файл war и скопировать его в каталог webapps tomcat. После этого вы сможете получить доступ к веб-сервису по следующему пути:
Http: // Localhost: 8080 / WS-привязки / addws
Где 8080 — это порт, на котором я размещал tomcat, а ws-bindings — это имя моего военного файла.

Наконец, давайте посмотрим, как создать клиентские заглушки, необходимые для нашего сервиса, а затем напишем небольшой клиент для тестирования нашего веб-сервиса.

  • Простой тестовый клиент для тестирования нашего сервиса

Мы снова будем использовать плагин apache-cxf maven для генерации заглушек клиента с помощью команды wsdl2java. Обратите внимание, что сначала нам нужно получить wsdl от пути, где размещен наш веб-сервис. Он будет расположен по адресу;

1
http://localhost:8080/ws-bindings/addws?wsdl

Затем я скопировал содержимое в отдельный XML-файл и сохранил его в каталоге ресурсов в отдельном проекте Maven, который я создал для создания заглушек клиента. Затем все, что вам нужно сделать, это добавить конфигурацию, необходимую для генерации заглушек в pom следующим образом;

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
     
<plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>2.0.9</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
 
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>${project.basedir}/src/main/resources/AddService.wsdl</wsdl>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Это создаст необходимые заглушки для тестирования вашего веб-сервиса. Наконец, позвольте нам написать клиент для использования сгенерированной заглушки для доступа к нашему веб-сервису;

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
     
import java.net.MalformedURLException;
import java.net.URL;
 
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
 
import com.wsbindings.AddService;
 
public class DocWrapperClient {
 
    public static void main(String[] args) throws MalformedURLException {
         URL wsdlLocation = new URL("http://localhost:8080/ws-bindings/addws?wsdl"); 
 
         QName qName = new QName("http://wsbindings.com/", "AddServiceImplService"); 
 
         Service service = null
         service = Service.create(wsdlLocation, qName); 
 
         AddService ser = service.getPort(AddService.class);
         System.out.println(ser.addIntegers(1, 1));
    }
}

Вот и все, ребята, и я надеюсь, что вы нашли содержание полезным. Вы можете проверить пример, загрузив отсюда связанный с сервером проект maven и отсюда клиентский проект maven поколения заглушек.

Ссылка: Давайте напишем веб-сервис в стиле документа от нашего партнера JCG Динуки Арурилератне в блоге My Journey By IT .