Главная » Spring » Контроллер главной страницы Spring

0

Обычно самое первое, что видят посетители веб-сайта, – это глав- ная страница. Это парадный вход, обеспечивающий доступ ко всей

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

В листинге 8.2 представлен контроллер HomeController – простей- ший контроллер Spring MVC, обслуживающий запросы на получе- ние главной страницы.

Листинг 8.2. Контроллер HomeController приветствует пользователей приложения Spitter

package  com.habuma.spitter.mvc; import    javax.inject.Inject; import java.util.Map;

import  org.springframework.beans.factory.annotation.Autowired; import    org.springframework.stereotype.Controller;

import    org.springframework.web.bind.annotation.RequestMapping; import     com.habuma.spitter.service.SpitterService;

@Controller                                                      // Объявить как контроллер public class HomeController {

public static final int DEFAULT_SPITTLES_PER_PAGE = 25; private   SpitterService   spitterService;

@Inject                                                      // Внедрить SpitterService

public  HomeController(SpitterService  spitterService)  { this.spitterService     =     spitterService;

}

@RequestMapping({"/","/home"})   // Обрабатывать запросы на получение

// главной страницы public String showHomePage(Map<String, Object> model) {

model.put("spittles",                  spitterService.getRecentSpittles( DEFAULT_SPITTLES_PER_PAGE));  //Добавить  сообщения  в  модель

return "home";                         // Вернуть имя представления

}

}

Несмотря на свою простоту реализации контроллера HomeController, о ней многое можно сказать. Во-первых, аннотация @Controller ука- зывает, что этот класс является классом контроллера. Данная анно-

тация является специализированной версией аннотации @Component, которая помогает элементу <context:component-scan> отыскивать и ре- гистрировать классы с аннотацией @Controller как компоненты, как если бы они были отмечены аннотацией @Component.

Это означает, что в файле spitterservlet.xml необходимо настроить элемент <context:component-scan>, чтобы обеспечить автоматическое обнаружение и регистрацию класса HomeController (и всех других классов контроллеров, которые нам предстоит написать) как компо- нента. Ниже приводится соответствующий фрагмент в XML-файле:

<context:component-scan  base-package="com.habuma.spitter.mvc"  />

Вернемся к классу HomeController. Мы знаем, что ему потребует- ся извлекать список последних сообщений посредством компонен- та SpitterService. Поэтому был создан конструктор, принимающий SpitterService в виде аргумента и отмеченный аннотацией @Inject, которая обеспечивает автоматическое внедрение при создании эк- земпляра контроллера.

Фактическую работу контроллера выполняет метод showHomePage(). Как видно из листинга 8.2, он отмечен аннотацией @RequestMapping. Эта аннотация преследует две цели. Во-первых, она превращает ме- тод showHomePage() в обработчик запросов. И, во-вторых, указывает, что этот метод должен вызываться для обработки запросов, содер- жащих путь / или /home.

Как обработчик запросов метод showHomePage() принимает отобра- жение (Map) строк в объекты. Это отображение представляет мо- дель – данные, передаваемые между контроллером и представле- нием. После получения списка последних сообщений (объектов Spittle) вызовом метода getRecentSpittles()  компонента SpitterService этот список помещается в модель model, благодаря чему представле- ние получит возможность отобразить его.

При создании других контроллеров будет показано, что сигна- тура метода обработки запросов может включать практически лю- бые аргументы. Даже при том, что методу showHomePage() необходи- ма только модель, ему можно было бы передать HttpServletRequest, HttpServletResponse, строки или числа, соответствующие параметрам запроса, значения в cookie, значения заголовков HTTP-запроса и массу других. Однако пока достаточно передать одну модель.

В конце метод showHomePage() должен вернуть строку с логическим именем представления, отображающего результаты. Класс контрол-

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

Настройка арбитра представлений будет выполнена ниже, но сна- чала напишем модульный тест, чтобы убедиться, что HomeController действует, как это ожидается.

Тестирование контроллера

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

С точки зрения модульного тестирования это очень важное об- стоятельство, потому что оно означает, что класс HomeController лег- ко можно протестировать без привлечения фиктивных или других объектов, зависящих от фреймворка Spring. В листинге 8.3 демон- стрируется класс HomeControllerTest, реализующий тестирование кон- троллера HomeController.

Листинг 8.3. Тест, позволяющий убедиться в корректной работе контроллера HomeController

package  com.habuma.spitter.mvc;

import static com.habuma.spitter.mvc.HomeController.*; import  static  java.util.Arrays.*;

import   static   org.junit.Assert.*; import static org.mockito.Mockito.*;

import  java.util.HashMap; import    java.util.List;

import org.junit.Test;

import   com.habuma.spitter.domain.Spittle;

import com.habuma.spitter.service.SpitterService;

public class HomeControllerTest {

@Test

public  void  shouldDisplayRecentSpittles()  {

List<Spittle>   expectedSpittles   =

asList(new Spittle(), new  Spittle(), new  Spittle());

// Фиктивный объект SpitterService

SpitterService   spitterService   =   mock(SpitterService.class);

when(spitterService.getRecentSpittles(DEFAULT_SPITTLES_PER_PAGE)). thenReturn(expectedSpittles);

// Создать контроллер HomeController controller =

new        HomeController(spitterService); HashMap<String,  Object>  model  =  new  HashMap<String,  Object>();

// Вызвать обработчик

String  viewName  =  controller.showHomePage(model); assertEquals("home",     viewName);

// Проверить результаты  assertSame(expectedSpittles,   model.get("spittles"));

verify(spitterService).getRecentSpittles(DEFAULT_SPITTLES_PER_PAGE);

}

}

Единственное, что необходимо контроллеру HomeController для вы- полнения своей работы, – экземпляр SpitterService, вместо которого передается фиктивная реализация, созданная с помощью фреймвор- ка Mockito1. После создания фиктивной реализации SpitterService остается лишь создать новый экземпляр класса HomeController и затем вызвать метод showHomePage(). В заключение проверяется, что список сообщений, возвращаемый фиктивной реализацией SpitterService, оказывается в модели с ключом spittles и что метод возвращает логическое имя home представления.

Как видите, тестирование контроллера Spring MVC мало чем от- личается от тестирования любого другого POJO в приложении на основе Spring. Даже при том, что в конечном итоге контроллер будет использоваться для обслуживания веб-страницы, нам не пришлось делать что-то особенное для его тестирования.

1   http://mockito.org.

На данный момент у нас имеется контроллер, обрабатывающий запросы на получение главной страницы, и тест, позволяющий убе- диться, что контроллер выполняет свою работу. Но пока без ответа остается еще один вопрос. Метод showHomePage() возвращает логиче- ское имя представления. Но как это имя будет использоваться для определения представления, отображающего страницу?

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

По теме:

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