На этом примере рассмотрим, как можно быстро научиться создавать веб-приложения, которые могут из микроприложений вырасти в серьезные проекты.
Содержание:
- Первоначальная настройка приложения
- Создание класса Task
- Создание интерфейса TaskRepository
- Создание класса TaskService
- Создание контроллера TaskController
- Создание шаблона для Freemarker
- Запуск приложения
Первоначальная настройка приложения
Переходим на сайт Spring Initializr и подготавливаем минимальный шаблон для нашего будущего приложения:
В левой части оставляем настройки по умолчанию, кроме версии Java (будет достаточно 8), и заполняем Project Metadata.
В правой части необходимо добавить зависимости, нужные для приложения.
- Spring Web — модуль, включающий необходимые компоненты для веб-приложения и имеющий встроенный контейнер сервлетов Apache Tomcat.
- Spring Data JPA — библиотека, используемая для взаимодействия с сущностями базы данных.
- H2 Database — очень удобная база данных. Располагается в памяти, следовательно, хранит данные только пока запущено приложение. Не используется в продакшене, но для знакомства в этом проекте её будет достаточно.
- Apache Freemarker — шаблонизатор, будем использовать его для генерации HTML-страниц.
Всё готово, нажимаем GENERATE и получаем архив с исходным кодом проекта. Это минимальный каркас, который импортируем в используемую IDE.
В этом проекте используется IntelliJ IDEA.
Следуем по пути File -> New -> Project from Existing Sources, в диалоговом окне выбираем папку, где находится pom.xml файл проекта. Импортируем проект.
В следующих диалоговых окнах все настройки оставляем по умолчанию. Единственное, в одном из окон удостоверимся, что имеем ранее установленную JDK соответствующей версии, в данном случае 8.
Если JDK не была установлена ранее, её можно скачать с официального сайта.
Все остальные окна кликаем Next и в последнем — Finish.
Кратко рассмотрим структуру проекта. В первую очередь интересны:
- файл pom.xml — файл с описанием всех зависимостей, необходимых для приложения;
- файл application.properties — файл с настройками проекта;
- каталог java — основной каталог пакетов и классов;
- каталог resources — каталог для хранения ресурсов (шаблоны, файлы настроек, локализации и т.д.).
Создадим дополнительные пакеты :
- entity — для сущностей, в текущем проекте это будет класс Task;
- controller — для классов контроллера;
- repository — для слоя Repository, интерфейс с описанием общих методов, которые будут использоваться при взаимодействии с базой данных;
- service — для классов с бизнес-логикой.
Основной сущностью данного приложения будет сущность Task, которая будет иметь идентификатор, описание задачи, дату выполнения, приоритет выполнения.
Создадим класс Task в пакете entity
package com.myorganization.Organizer.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Date;
@Entity
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private Integer priorityId;
private String description;
private Date date;
public Task() {
}
public Task(Integer id, Integer priorityId, String description, Date date) {
this.id = id;
this.priorityId = priorityId;
this.description = description;
this.date = date;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getPriorityId() {
return priorityId;
}
public void setPriorityId(Integer priorityId) {
this.priorityId = priorityId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
Класс помечен аннотацией @Entity. Она указывает на то, что данный класс является сущностью и будет сохраняться в БД.
Данная сущность имеет первичный ключ поле id. Поле помечено аннотацией @Id и аннотацией @GeneratedValue, которая задает стратегию генерации первичного ключа как автоматическую генерацию, в этой сущности – целые числа в порядке возрастания.
Создадим интерфейс TaskRepository в пакете repository
package com.myorganization.Organizer.repository;
import com.myorganization.Organizer.entity.Task;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TaskRepository extends JpaRepository<Task, Integer> {
}
Класс унаследован от JpaRepository – интерфейса фреймворка Spring Data, предоставляющего набор стандартных методов JPA для работы с БД. Для данного приложения нет необходимости создавать дополнительные методы.
Создадим класс TaskService в пакете service
package com.myorganization.Organizer.service;
import com.myorganization.Organizer.entity.Task;
import com.myorganization.Organizer.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskService {
@Autowired
private TaskRepository taskRepository;
public List<Task> getAll() {
return taskRepository.findAll(Sort.by(Sort.Order.asc("date"),
Sort.Order.desc("priorityId")));
}
public Task save(Task task) {
return taskRepository.save(task);
}
public void delete(int id) {
taskRepository.deleteById(id);
}
}
Класс содержит три метода для работы с задачами:
- getAll() – метод, возвращающий все задачи, отсортированные в порядке возрастания даты и порядке убывания приоритета.
- save(Task task) – метод создания новой задачи.
- delete(int id) – метод, удаляющий задачу по переданному id.
Создадим контроллер TaskController в пакете controller
package com.myorganization.Organizer.controller;
import com.myorganization.Organizer.entity.Task;
import com.myorganization.Organizer.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/")
public String getAll(Model model) {
List<Task> taskList = taskService.getAll();
model.addAttribute("taskList", taskList);
model.addAttribute("taskSize", taskList.size());
return "index";
}
@RequestMapping("/delete/{id}")
public String deleteTask(@PathVariable int id) {
taskService.delete(id);
return "redirect:/";
}
@PostMapping("/add")
public String addTask(@ModelAttribute Task task) {
taskService.save(task);
return "redirect:/";
}
}
Класс контроллер содержит три метода для управления задачами. При вызове методы обращаются в сервис TaskService, производят необходимые действия с сущностью и перенаправляют по заданному пути.
Замечание. Более правильно было бы добавить еще один интерфейс TaskService, который будет реализовывать существующий класс TaskService (изменим название на TaskServiceImpl), но в рамках этого приложения делать это не будем.
Создадим index.ftlh – шаблон для Freemarker в каталоге resources/templates
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Organizer</title>
<link rel="stylesheet" type="text/css" href="/css/style.x20492.css"/>
</head>
<body>
<h1>Organizer</h1>
<h3>Add task to list</h3>
<form action="/add" method="post">
<table border="1px">
<tr>
<td>
<label>Priority</label>
<input type="number" name="priorityId">
</td>
<td>
<label>Description</label>
<input type="text" name="description">
</td>
<td>
<label>Date</label>
<input type="date" name="date">
</td>
<td>
<input type="submit" value="add task">
</td>
</tr>
</table>
</form>
<br>
<h2>Task list(task count : ${taskSize})</h2>
<table border="1px">
<tr>
<td>Id</td>
<td>Priority</td>
<td>Task description</td>
<td>Date</td>
<td>Delete from list</td>
</tr>
<#list taskList as task>
<tr>
<td>${task.id}</td>
<td>${task.priorityId}</td>
<td>${task.description}</td>
<td>${task.date}</td>
<td><a href="${'/delete/'+task.id}"">Delete</a></td>
</tr>
</#list>
</table>
</body>
</html>
Стандартный HTML-файл. Единственное отличие – это конструкции вида ${….} и обозначение списка <#list ….>, вместо которых Freemarker подставит нужные нам значения.
Добавим простой CSS-файл style.css в каталоге resources/static/css:
table {
border-collapse: collapse;
}
table th, table td {
padding: 2px;
}
Структура проекта:
Запускаем первое приложение на Spring Boot
Переходим к классу OrganizerApplication.class. Он был сформирован автоматически на первом шаге конфигурации каркаса проекта. Его содержимое:
package com.myorganization.Organizer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrganizerApplication {
public static void main(String[] args) {
SpringApplication.run(OrganizerApplication.class, args);
}
}
Переходим в меню >Run-> Run ‘OrganizerApplication’ или запускаем через сочетание клавиш Shift+F10. Процесс запуска отобразится в консоли ниже.
Переходим в браузер, набираем в адресной строке адрес localhost:8080 и наблюдаем работающий прототип приложения Organizer.
Так с помощью Spring Boot с минимальным набором классов менее чем за час можно создать работающее веб-приложение или основу для будущих проектов. Это уже тема другой статьи.
Посмотрите также 10 шпаргалок для веб-разработчика. Там есть видеокурс по Spring Boot.