Главная » Spring » Создание конечной точки на основе модели JDOM Spring

0

Веб-служба, оценивающая комбинацию карт при игре в покер, принимает сообщение <EvaluateHandRequest> и возвращает сообщение

<EvaluateHandResponse>. То есть нам необходимо создать конечную точку веб-службы, обрабатывающую элемент <EvaluateHandRequest> и возвращающую элемент <EvaluateHandResponse>.

Для этого можно использовать любой из абстрактных классов конечных точек, перечисленных в табл. 15.2, но мы выберем класс AbstractJDomPayloadEndpoint. Отчасти выбор был сделан случайно, но лично мне нравится поддержка XPath в JDOM, обеспечивающая простой способ извлечения информации из элементов Element в мо- дели JDOM. (За дополнительной информацией о модели JDOM обращайтесь на домашнюю страницу проекта: http://www.jdom.org.) Класс EvaluateHandJDomEndpoint (листинг 15.2) наследует класс Abst- ractJDomPayloadEndpoint  и предоставляет функциональность, необхо-

димую для обработки сообщения <EvaluateHandRequest>.

Листинг 15.2. Конечная точка для обработки сообщений

<EvaluateHandRequest>

package  com.springinaction.poker.webservice; import     java.util.Iterator;

import    java.util.List; import org.jdom.Element;

import  org.jdom.JDOMException; import   org.jdom.Namespace; import      org.jdom.xpath.XPath;

import     org.springframework.beans.factory.InitializingBean;

import    org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint; import  com.springinaction.poker.Card;

import  com.springinaction.poker.Face; import    com.springinaction.poker.PokerHand;

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

public class EvaluateHandJDomEndpoint   extends   AbstractJDomPayloadEndpoint implements   InitializingBean   {

private Namespace namespace; private  XPath  cardsXPath;

private  XPath  suitXPath; private XPath faceXPath;

protected Element invokeInternal(Element element) throws Exception {

Card    cards[]    =    extractCardsFromRequest(element); PokerHand pokerHand = new PokerHand(); pokerHand.setCards(cards);

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

return createResponse(handType);

}

private Element createResponse(PokerHandType handType) {// Создает ответ Element responseElement =

new Element("EvaluateHandResponse", namespace); responseElement.addContent(

new Element("handName", namespace).setText( handType.toString()));

return responseElement;

}

private  Card[]  extractCardsFromRequest(Element  element) throws JDOMException {

Card[]  cards  =  new  Card[5];

// Извлечь карты из сообщения

List cardElements = cardsXPath.selectNodes(element); for(int  i=0;  i <  cardElements.size();  i++)  {

Element cardElement = (Element) cardElements.get(i); Suit  suit  =  Suit.valueOf(

suitXPath.valueOf(cardElement)); Face  face  =  Face.valueOf(

faceXPath.valueOf(cardElement)); cards[i]  =  new  Card(); cards[i].setFace(face); cards[i].setSuit(suit);

}

return cards;

}

public  void  afterPropertiesSet()  throws  Exception  {

namespace  =  Namespace.getNamespace("poker", "http://www.springinaction.com/poker/schemas");

// Подготовить XPath-запросы cardsXPath =

XPath.newInstance("/poker:EvaluateHandRequest/poker.card"); cardsXPath.addNamespace(namespace);

faceXPath     =     XPath.newInstance("poker:face"); faceXPath.addNamespace(namespace);

suitXPath    =    XPath.newInstance("poker:suit"); suitXPath.addNamespace(namespace);

}

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

private  PokerHandEvaluator  pokerHandEvaluator; public  void  setPokerHandEvaluator(

PokerHandEvaluator   pokerHandEvaluator)   { this.pokerHandEvaluator    =    pokerHandEvaluator;

}

}

Метод invokeInternal() – это точка входа в данную  конечную точку. При вызове ему передается JDOM-объект Element, содержа- щий входящее сообщение, в данном случае <EvaluateHandRequest>. Метод invokeInternal() передает объект Element методу extractCards- FromRequest(), который с помощью объектов JDOM XPath извлекает информацию о картах из элемента <EvaluateHandRequest>.

После получения массива объектов Card метод invokeInternal() передает их внедренному объекту PokerHandEvaluator для оценки комбинации карт. Объект PokerHandEvaluator реализует следующий интерфейс:

package  com.springinaction.poker; public interface PokerHandEvaluator {

PokerHandType  evaluateHand(PokerHand  hand);

}

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

Тот факт, что точка входа вызывает метод evaluateHand() класса PokerHandEvaluator, имеет большое значение. Правильно спроектиро- ванная конечная точка Spring-WS не должна выполнять какую-либо прикладную логику. Она должна играть роль лишь передаточного звена между клиентом и внутренним API. Фактическая прикладная логика выполняется реализацией интерфейса in PokerHandEvaluator. Подобную организацию мы уже видели в главе 8, где контроллеры Spring MVC играли роль посредников между пользователем и объ- ектами на стороне сервера.

Как только PokerHandEvaluator определит значение комбинации карт, метод invokeInternal() передаст объект PokerHandType методу createResponse(), чтобы произвести ответ <EvaluateHandResponse>, и пос- ле получения объекта Element класс EvaluateHandJDomEndpoint завершает работу.

EvaluateHandJDomEndpoint – отличный пример реализации конечной точки Spring-WS. Но в ней присутствует множество специфических особенностей, имеющих отношение к формату XML. Даже при том, что сообщения, обрабатываемые конечными точками Spring-WS, имеют формат XML, нет никаких причин, почему конечная точка должна быть реализована с учетом этой особенности. Посмотрим далее, как с помощью механизма маршалинга избавиться от опера- ций, связанных с парсингом XML-сообщений.

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

По теме:

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