Тэги: Spring Boot, rest, json, Java.
Spring Boot значительно упрощает преобразование объекта в json. Предположим, у нас есть такой класс, содержащий какую-то информацию о пользователе:
Создадим контроллер, который будет его возвращать.
Этих двух классов достаточно, чтобы вы уже могли получать информацию о пользователе в формате json! Выполнив GET-запрос к вашему приложению (по умолчанию http://127.0.0.1:8080/), вы получите такой json:
Тэги: Stream API, Java.
Предположим, у нас есть дата начала dateTill и дата окончания dateFrom некоторого временного диапазона. И нам нужно получить список, содержащий все даты из этого диапазона. Как это сделать? Есть два варианта.
Если у вас Java версии 9 или более поздняя, то можно использовать такой лаконичный вариант:
Метод LocalDate.datesUntil() порождает поток, начинающийся с указанной даты и заканчивающийся датой, переданной в этот метод в качестве параметра. Чтобы конечная дата также попала в выборку, прибавляем к ней ещё один день с помощью метода plusDays(). В конце превращаем этот поток в список, используя метод collect().
При разработке приложений иногда бывает необходимо выбрать случайный элемент из некоторого множества. Предположим, что у нас есть список фруктов и нам нужно выбрать случайным образом один из них.
Сначала создадим генератор случайных значений SecureRandom. Можно также использовать и обычный Random, но первый выдаёт более случайные значения.
Тэги: Java.
В простых консольных утилитах может возникнуть небходимость чтения данных, которые пользователь вводит с консоли. Сделать это можно с помощью стандартного класса Scanner.
В конструктор этого класса передаётся стандартный поток ввода System.in. Далее мы запрашиваем у пользователя его имя с помощью метода nextLine(). Этот метод вернёт всю строку, которую введёт пользователь в консоли до нажатия клавиши Enter.
Spring позволяет проверять формат данных в бинах в декларативном стиле при помощи специальных аннотаций из пакета javax.validation.
Предположим, у нас есть rest-контроллер, в который мы хотим добавить метод, создающий пользователя. Очевидно, что это будет POST-запрос:
На вход метод принимает бин CreateUserRequest, который мы будем передавать в формате json. Этот параметр метода снабжён аннотациями @RequestBody (говорит, что параметр будет именно в теле запроса) и @Valid (аннотация, которая активирует механизм валидации для данного бина). Обратите внимание, что если не указать аннотацию @Valid, то валидация работать не будет.
Тэги: Spring Boot, rest, Java, yaml, файлы.
Значения параметров системы удобно отделять от программного кода, чтобы можно было их менять без перекомпиляции всего приложения. Spring Boot предоставляет нам удобный способ работы с конфигурационными файлами. Ниже мы рассмотрим несколько случаев, начиная с самого простого.
Исходники доступны на github.
Отдельное свойство можно внедрить в любой компонент Spring при помощи аннотации @Value.
Предположим, у нас есть простейшее Spring Boot приложение, в котором есть rest-контроллер с методами.
Добавим метод, который в ответ возвращает приветственный текст для пользователя, а имя пользователя будем брать из конфига.
Тэги: Java, многопоточность.
Есть два способа создания потоков в Java: унаследоваться от класса Thread или реализовать интерфейс Runnable.
Рассмотрим пример, в котором мы расширяем стандартный класс Thread, переопределяя лишь один метод run(). В нём мы ждём 3 секунды, а затем выводим сообщение о завершении потока. Обратите внимание, что запуск потока осуществляется не через метод run(), а через метод start().
Метод TimeUnit.SECONDS.sleep() полностью эквивалентен стандартному Thread.sleep(), однако в первом случае мы явно указываем единицы измерения времени, что делает код более читаемым. Я рекомендую использовать именно такую форму записи.
Поскольку метод sleep() относится к низкоуровневым, он может кидать InterruptedException, которое свидетельствует о том, что поток был прерван. Это исключение является единственным признаком того, что поток был принудительно остановлен. И чтобы не терять эту информацию в стеке вызовов, мы выставляем флаг interrupted при помощи соответствующего метода Thread.currentThread(). Такой способ обработки InterruptedException является правильным и именно его нужно использовать в подобных случаях.
Тэги: Collections, Java.
Ранее мы рассматривали наиболее популярные Коллекции: list, set, map. В данной статье рассмотрим чуть более специфичные коллекции. Все рассмотренные ниже коллекции реализуют один из двух алгоритмов манипулирования данными: «First In – First Out» (FIFO) и «Last In – First Out» (LIFO).
Очередь реализует принцип «first in – first out», т.е. «первым пришёл – первым ушёл». Базовым интерфейсом всех очередей Java является Queue. Добавление элементов в очередь делается методом add(), удаление – poll(), получение первого элемента без его удаления – peek().
Две самые простые реализации очереди – это LinkedList и PriorityQueue. Рассмотрим их на примере.
Тэги: Spring Boot, maven, PostgreSQL, rest, Spring, Java, Hibernate.
Ранее мы уже рассматривали, как работать с базой данных через jdbc в статье Работа с БД в Spring Boot на примере postgresql. А сегодня возьмём Hibernate – самый популярный фреймворк для работы с БД – и убедимся, что он значительно облегчает реализацию типовых операций над сущностями.
Предположим, в БД у нас есть две сущности: страна и город. В одной стране может быть несколько городов (отношение «один-ко-многим»). Структура таблиц выглядит примерно так:
И мы хотим совершать типовые действия над этими сущностями: просмотр всего списка, поиск по id, добавление, обновление и удаление записей. Для этого создадим типовой Spring Boot проект. В pom-файле нужно прописать следующий parent:
Тэги: Spring Boot, Java, PostgreSQL.
В предыдущих статьях мы уже создавали rest-приложение (Spring Boot Restful Service, Работа с БД в Spring Boot на примере postgresql). А теперь давайте рассмотрим, как работать с датой и временем в Spring Boot на уровне rest-запросов и на уровне БД.
Предположим, перед нами стоит задача фиксировать в специальной таблице все действия пользователя (регистрация, вход, выход и т.п.) Таблица для СУБД Postgres в самом простом случае будет выглядеть так:
Тип serial представляет собой поле, которое автоматически увеличивается на единицу для каждой новой записи, поэтому его удобно использовать в качестве первичного ключа для записи.
Тип timestamp without time zone позволяет хранить метку времени без привязки к часовому поясу.
user_id и action_type представляют собой числовые id пользователя и тип действия соответственно. В реальном приложении каждое из них должно быть внешним ключом на соответствующие таблицы, но в нашем примере для простоты такой привязки нет.
Kotlin, Java, Java 11, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.