Главная » Spring » Маршалинг содержимого сообщений Spring

0

Как отмечалось выше, класс AbstractMarshallingPayloadEndpoint не- сколько отличается от других абстрактных классов конечных точек в Spring-WS. Вместо XML-элемента конечная точка AbstractMarshal- lingPayloadEndpoint получает Java-объект для обработки.

Фактически, как показано на рис. 15.4, конечная точка действует в паре с демаршалером, преобразующим XML-сообщения в POJO. Завершив обработку, конечная точка просто возвращает POJO, а маршалер превращает его в XML-сообщение, которое затем пе- редается клиенту. Такой подход позволяет существенно упростить реализацию конечной точки, так как ей не приходится заниматься обработкой разметки XML.

Например, рассмотрим листинг 15.3, где приводится новая реа- лизация конечной точки – класс EvaluateHandMarshallingEndpoint, на- следующий класс AbstractMarshallingPayloadEndpoint.

Рис. 15.4. Конечная точка снабжается промежуточным объектом, занимающимся промежуточными преобразованиями XML-сообщений, благодаря чему конечной точке приходится работать

только с простыми Java-объектами

Листинг 15.3. Конечная точка, обрабатывающая сообщения

<EvaluateHandRequest>

package  com.springinaction.poker.webservice;

import org.springframework.ws.server.endpoint.AbstractMarshallingPayloadEndpoint; import    com.springinaction.poker.PokerHand;

import     com.springinaction.poker.PokerHandEvaluator; import   com.springinaction.poker.PokerHandType;

public class EvaluateHandMarshallingEndpoint

extends  AbstractMarshallingPayloadEndpoint  {

// Передает в конечную точку реализацию EvaluateHandRequest protected  Object  invokeInternal(Object  object)

throws  Exception  { EvaluateHandRequest   request   =

(EvaluateHandRequest) object;

PokerHand pokerHand = new PokerHand(); pokerHand.setCards(request.getHand());

PokerHandType pokerHandType =              // Оценивает комбинацию карт pokerHandEvaluator.evaluateHand(pokerHand);

return  new  EvaluateHandResponse(pokerHandType);

}

// внедряется

private  PokerHandEvaluator  pokerHandEvaluator; public  void  setPokerHandEvaluator(

PokerHandEvaluator   pokerHandEvaluator)   { this.pokerHandEvaluator    =    pokerHandEvaluator;

}

}

Первое, на что следует обратить внимание, – класс EvaluateHand- MarshallingEndpoint получился намного короче класса EvaluateHand- JDomEndpoint. Это обусловлено отсутствием в классе EvaluateHandMar- shallingEndpoint операций парсинга разметки XML, которые были необходимы в классе EvaluateHandJDomEndpoint.

В этой версии методу invokeInternal() передается объект Object. В данном случае – объект класса EvaluateHandRequest:

package  com.springinaction.poker.webservice; import  com.springinaction.poker.Card;

public class EvaluateHandRequest { private  Card[]  hand;

public  EvaluateHandRequest()  {} public  Card[]  getHand()  {

return hand;

}

public  void  setHand(Card[]  cards)  { this.hand  =  cards;

}

}

С другой стороны, метод invokeInternal() возвращает объект Eva- luateHandResponse. Ниже приводится определение класса EvaluateHand- Response:

package     com.springinaction.poker.webservice; import   com.springinaction.poker.PokerHandType;

public  class  EvaluateHandResponse  { private PokerHandType pokerHand;

public  EvaluateHandResponse()  { this(PokerHandType.NONE);

}

public  EvaluateHandResponse(PokerHandType  pokerHand)  { this.pokerHand   =   pokerHand;

}

public PokerHandType getPokerHand() {

return this.pokerHand;

}

public  void  setPokerHand(PokerHandType  pokerHand)  { this.pokerHand   =   pokerHand;

}

}

Но как входящее XML-сообщение <EvaluateHandRequest> преоб- разуется в объект EvaluateHandRequest? И как возвращаемый объект EvaluateHandResponse превращается в сообщение <EvaluateHandResponse>, отправляемое клиенту?

От наших глаз укрылось одно обстоятельство: класс AbstractM arshallingPayloadEndpoint имеет ссылку на объект, выполняющий маршалинг разметки XML. Когда класс конечной точки получа- ет XML-сообщение, перед вызовом invokeInternal() он с помощью демаршалера превращает XML-сообщение в объект. Затем, ког- да  invokeInternal()  завершится,  маршалер  превратит  Java-объект в XML-сообщение.

Значительную часть фреймворка Spring-WS составляет реализа- ция механизмов отображения объектов в XML и обратно (Object- XML Mapping, OXM). Фреймворк Spring-WS включает несколько реализаций OXM, включая:

# JAXB (версии 1 и 2);

#  Castor XML;

# JiBX;

# XMLBeans;

# XStream.

Кого-то может заинтересовать вопрос, какой из механизмов OXM я выбрал для реализации EvaluateHandMarshallingEndpoint. Я от- вечу на этот вопрос, но не сейчас. Важно отметить, что EvaluateHand- MarshallingEndpoint понятия не имеет, откуда берется объект Object, передаваемый методу invokeInternal(). Фактически объект Object во- обще может быть создан не на основе разметки XML.

Это обстоятельство подчеркивает ключевое преимущество ко- нечной точки с маршалингом. Поскольку теперь класс EvaluateHand- MarshallingEndpoint получает простой объект, он легко может быть подвергнут модульному тестированию, подобно любому другому POJO. Испытательный тест может просто передавать конечной точ- ке объект EvaluateHandRequest и выполнять проверки возвращаемого объекта EvaluateHandResponse.

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

Связываем все вместе

Мы наконец достигли заключительной стадии разработки служ- бы Spring-WS. Теперь необходимо сконфигурировать контекст при- ложения Spring, внедрив в него компонент конечной точки и неко- торые компоненты, образующие инфраструктуру Spring-WS.

Фреймворк Spring-WS основан на фреймворке Spring MVC (ко- торый описывался в главе 8). В Spring MVC все запросы попадают в специальный сервлет DispatcherServlet, который передает запросы классам контроллеров для обработки. Аналогичным образом дей- ствует и фреймворк Spring-WS: запросы сначала попадают в сервлет MessageDispatcherServlet, подкласс класса DispatcherServlet, который передает SOAP-запросы конечным точкам Spring-WS1.

MessageDispatcherServlet – это удивительно простой сервлет, и его можно настроить в файле web.xml веб-приложения с помощью эле- ментов <servlet> и <servletmapping>, как показано ниже:

<servlet>

<servlet-name>poker</servlet-name>

<servlet-class>org.springframework.ws.transport.http.

➥    MessageDispatcherServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>poker</servlet-name>

<url-pattern>/services/*</url-pattern>

</servlet-mapping>

К конфигурации сервлета MessageDispatcherServlet мы еще вернем- ся чуть ниже, а пока немного отвлечемся.

1 Считается, что приставка «веб» в слове «веб-служба» предполагает работу всех веб-служб по протоколу HTTP. Но это не так. Фреймворк Spring-WS поддерживает создание веб-служб, действующих по протоколам JMS и электронной почты, а также на основе низкоуровневого протокола TCP/ IP. Однако, так как большинство веб-служб фактически действуют по протоколу HTTP, именно этот протокол и будет подразумеваться в опи- сываемой конфигурации.

MessageDispatcherServlet – единственный входной контроллер (front controller) в Spring-WS. Однако фреймворк Spring-WS со- держит еще ряд компонентов, которые также необходимо внедрить в контекст приложения Spring. Познакомимся с этими компонента- ми поближе.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии