Аватарка пользователя Юрий Авраменко
Юрий Авраменко

Spring Boot: быстрое знакомство и старт на примере простого веб-приложения

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

25737

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

Содержание:

Первоначальная настройка приложения

Переходим на сайт 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 {

}
		

Класс унаследован от 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 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 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

			


    
    Organizer
      


Organizer

Add task to list


Task list(task count : ${taskSize})

<#list taskList as task>
Id Priority Task description Date Delete from list
${task.id} ${task.priorityId} ${task.description} ${task.date} Delete

Стандартный 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.

Следите за новыми постами по любимым темам

Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.

Java
Веб-разработка
Приложение
Пост пользователя
25737
Что думаете?
8 комментариев
Сначала интересные
Аватар
Приложение работает до момента добавления задачи. После нажатия на add выпадает следующая страница : "
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Wed Mar 02 17:32:03 KRAT 2022 There was an unexpected error (type=Bad Request, status=400)." Что делать?
Аватар пользователя Олексій Тихий
TommySnatch, В класе Task укажите в аннотации формат даты перед обьявлением поля 

@DateTimeFormat(pattern = "yyyy-MM-dd") 
 private Date date;
Аватар пользователя Zhassurbek Boltabayev
Олексій Тихий, Не помогло
Аватар пользователя Nikita Anuryev
Zhassurbek Boltabayev, В дополнение к этому в классе Task нужно объявить пустой конструктор (либо аннотация  @NoArgsConstructor библиотеки Lombok).
У меня заработало
Аватар
При старте приложения выдает следующую ошибку: Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. 
Пустой конструктор есть. Версия JDK 1.8.
Аватар пользователя Vladimir Isaev
Добрый день. Всё отлично, однако, при записи даты происходит ошибка (несовпадение типов данных) ""Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2022-11-22'; Я перерыл код но нигде явно не увидел попытки записи типа String в Date/   

Помогло добаление в аннотации указания формата даты. 

@DateTimeFormat(pattern = "yyyy-MM-dd") private Date date;

Всё работает спасибо, едем дальше !
Аватар пользователя Eugene
Vladimir Isaev, Копался сам с этой ошибкой, а нужно было комментарии прочесть!  Спасибо!
Показать все комментарии