Spring in Action Covers Spring 5-1--11 — страница 7 из 63

Листинг 2.1 Определение ингредиента тако

package tacos;

import lombok.Data;


import lombok.RequiredArgsConstructor;



@Data


@RequiredArgsConstructor


public class Ingredient {


 private final String id;


 private final String name;


 private final Type type;



 public static enum Type {


   WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE


 }


}

Как вы можете видеть, это заурядный класс домена Java, определяющий три свойства, необходимые для описания ингредиента. Возможно, самое необычное в классе Ingredient, как он определен в листинге 2.1, заключается в том, что в нем отсутствует обычный набор методов getter и setter, не говоря уже о таких полезных методах, как equals (), hashCode (), toString () и других.

Вы не видите их в списке частично, чтобы сэкономить место, но и потому, что вы используете удивительную библиотеку под названием Lombok для автоматического создания этих методов во время выполнения. Фактически, аннотация @Data на уровне класса предоставляется Lombok и указывает Lombok генерировать все эти отсутствующие методы, а также конструктор, который принимает все конечные свойства в качестве аргументов. Путем использование Lombok, вы можете держать код для Ingredient коротким и понятным.

Lombok-это не Spring-овая библиотека, но она настолько невероятно полезна, что мне уже трудно без нее. И она спасает, когда мне нужно чтобы примеры кода в книге были короткими и понятными.

Чтобы использовать Lombok, вам нужно добавить его в качестве зависимости в свой проект. Если вы используете Spring Tool Suite, это простой вопрос, щелкнув правой кнопкой мыши на pom.xml-файл и выбор редактировать стартеры из опции контекстного меню Spring. Появится тот же выбор зависимостей, что и в главе 1 (на рис. 1.4), что дает вам возможность добавить или изменить выбранные зависимости. Найдите выбор Lombok, убедитесь, что он отмечен, и нажмите OK; Spring Tool Suite автоматически добавит его в вашу спецификацию сборки.

Кроме того, можно вручную добавить его со следующей записью в pom.xml:


org.projectlombok


lombok


true


Эта зависимость предоставит вам аннотации Lombok (например, @Data) во время разработки и с автоматической генерацией методов во время выполнения. Но вам также потребуется добавить Lombok в качестве расширения в IDE, иначе IDE будет жаловаться на ошибки, связанные с отсутствующими методами и конечными свойствами, которые не задаются. Посетите https://projectlombok.org/ чтобы узнать, как установить Lombok в выбранной среде IDE.

Я думаю, что вы найдете Ломбок очень полезным, но знайте, что он необязателен. Он не нужен для разработки приложений Spring, поэтому если вы не хотите его использовать, не стесняйтесь писать эти недостающие методы вручную. Дерзайте... Я подожду.

2.1.2 Создание класса контроллера

Контроллеры являются основными компонентами в рамках Spring MVC. Их основная задача-обрабатывать HTTP-запросы и либо передать запрос в представление для отображения HTML (отображаемого браузером), либо записать данные непосредственно в тело ответа (RESTful). В этой главе мы сосредоточимся на типах контроллеров, использующих представления для создания содержимого для веб-браузеров. Когда мы перейдем к главе 6, мы рассмотрим написание контроллеров, которые обрабатывают запросы в REST API.

Для Taco Cloud, вам нужен простой контроллер который делает следующее:

Обрабатывать HTTP-запросы GET, для пути запроса /design

Составьте список ингредиентов

Обработать запрос и данные по ингредиентам на основе шаблона для отображения как HTML и отправить в веб-браузер.

Следующий класс DesignTacoController отвечает этим требованиям

Листинг 2.2 Начальный класс Spring контроллера

package tacos.web;

import java.util.Arrays;


import java.util.List;


import java.util.stream.Collectors;


import javax.validation.Valid;


import org.springframework.stereotype.Controller;


import org.springframework.ui.Model;


import org.springframework.validation.Errors;


import org.springframework.web.bind.annotation.GetMapping;


import org.springframework.web.bind.annotation.PostMapping;


import org.springframework.web.bind.annotation.RequestMapping;


import lombok.extern.slf4j.Slf4j;


import tacos.Taco;


import tacos.Ingredient;


import tacos.Ingredient.Type;



@Slf4j


@Controller


@RequestMapping("/design")


public class DesignTacoController {



   @GetMapping


   public String showDesignForm(Model model) {


      List ingredients = Arrays.asList(


         new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),


         new Ingredient("COTO", "Corn Tortilla", Type.WRAP),


         new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),


         new Ingredient("CARN", "Carnitas", Type.PROTEIN),


         new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),


         new Ingredient("LETC", "Lettuce", Type.VEGGIES),


         new Ingredient("CHED", "Cheddar", Type.CHEESE),


         new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),


         new Ingredient("SLSA", "Salsa", Type.SAUCE),


         new Ingredient("SRCR", "Sour Cream", Type.SAUCE)


      );


      Type[] types = Ingredient.Type.values();


      for (Type type : types) {


         model.addAttribute(type.toString().toLowerCase(),


         filterByType(ingredients, type));


      }


      model.addAttribute("design", new Taco());


      return "design";


   }

}

Первое, что следует отметить об DesignTacoController, - это набор аннотаций, применяемых на уровне класса. Первый, @Slf4j, является аннотацией, предоставляемой Lombok, которая во время выполнения автоматически генерирует SLF4J (Simple Logging Facade for Java, https://www.slf4j.org/) Logger в классе. Эта скромная аннотация имеет тот же эффект, что и при явном добавлении следующих строк в класс:

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DesignTacoController.class);

Вы будете использовать этот Logger немного позже.

Следующая аннотация, примененная к DesignTacoController это - @Controller. Эта аннотация служит, чтобы идентифицировать этот класс как контроллер и пометить его как кандидата на компонентное сканирование, так, чтобы Spring обнаружил его и автоматически создал экземпляр DesignTacoController как bean в контексте приложения Spring.

DesignTacoController аннотирован @RequestMapping. @RequestMapping аннотация, используемая на уровне класса, определяет тип запросов, обрабатываемых этим контроллером. В этом случае он указывает, что контроллер DesignTacoController будет обрабатывать запросы, путь к которым начинается с /design.

ОБРАБОТКА ЗАПРОСА GET

@GetMapping - относительно новая аннотация, появившаяся в Spring 4.3. До Spring 4.3 вы, возможно, использовали аннотацию @RequestMapping уровня метода вместо:

@RequestMapping(method=RequestMethod.GET)

Очевидно, что @GetMapping более сжатый и конкретный метод HTTP. @GetMapping является лишь одним членом семьи request-mapping аннотации. В таблице 2.1 перечислены все аннотации request-mapping, доступные в Spring MVC.

Таблица 2.1 Spring MVC request-mapping аннотации


Аннотации

Описание


@RequestMapping

обработка запросов общего назначения


@GetMapping

обрабатывает запросы HTTP GET


@PostMapping

обрабатывает запросы HTTP POST


@PutMapping

обрабатывает запросы HTTP PUT


@DeleteMapping

обрабатывает HTTP-запросы на удаление


@Pathmapping

обрабатывае HTTP-запросов на патч


Делайте правильные вещи легкими

Всегда рекомендуется быть как можно более конкретным при объявлении сопоставлений запросов в методах контроллера. По крайней мере, это означает объявление как пути (или наследование пути от класса уровня @RequestMapping), так и метода HTTP, который он будет обрабатывать.

Длинный @RequestMapping((method=RequestMethod.GET) сделал заманчивым взять ленивый выход и оставить атрибут метода. Благодаря новым аннотациям отображения Spring 4.3, правильная вещь также является легкой - с меньшим количеством ввода.

Новые аннотации request-mapping имеют те же атрибуты, что и @RequestMapping, поэтому их можно использовать везде, где пришлось бы использовать @RequestMapping.

Как правило, я предпочитаю использовать только @RequestMapping на уровне класса, чтобы указать базовый путь. Я использую более конкретные @GetMapping, @PostMapping и т. д. Для каждого из методов обработчика.

Теперь, когда вы знаете, что метод showDesignForm() будет обрабатывать запрос, давайте посмотрим на тело метода, чтобы увидеть, как он устроен. Основное - это то что метод создает список объектов Ingredient. Список пока жестко закодирован. Когда мы к этому вернемся в главе 3, вы получите список доступных ингредиентов тако из базы данных

Как только список ингредиентов готов, следующие несколько строк showDesignForm() фильтруют список по типу ингредиентов. Затем список типов ингредиентов добавляется в качестве атрибута к объекту Model, который передается в showDesignForm()). Model - объект, который передает данные между контроллером и любым представлением, отвечающим за визуализацию этих данных. В конечном счете данные, помещенные в атрибуты Model, копируются в атрибуты ответа сервлета, где их можно найти в представлении. Метод showDesignForm() завершается возвратом "design", логическим именем представления, которое будет использоваться для отображения модели в браузере.