Spring Boot: можно использовать
✅ Один из возможных поводов сделать это когда у тебя есть своя конфигурация, которая конфликтует со стандартной.
👉 Java Portal
@SpringBootApplication(exclude = …), чтобы отключить определённые классы автоконфигурации.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🤔1
Если нужно внедрить сгруппированные конфигурационные параметры в классы, можно использовать аннотацию
👉 Java Portal
@ConfigurationProperties вместо @Value@Value обычно применяют для внедрения отдельных свойств:@Value("${app.name}")
private String appName;@ConfigurationProperties лучше подходит для более сложных, сгруппированных настроек:email:
host: smtp.example.com
port: 587
username: [email protected]
password: secret
@Component
@ConfigurationProperties(prefix = "email")
public class EmailProperties {
private String host;
private int port;
private String username;
private String password;
// геттеры и сеттеры
}
@Service
public class EmailService {
private final EmailProperties emailProperties;
public EmailService(EmailProperties emailProperties) {
this.emailProperties = emailProperties;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2🔥1
Разбор логов при запуске Spring Boot
Когда запускаешь Spring Boot и в консоли пролетают тонны логов - вот что это всё значит:
1. Spring Boot Banner
Сначала появляется ASCII-баннер с версией Spring Boot:
:: Spring Boot :: (v3.3.4)
Он показывает версию приложения и данные JVM.
2. Стартовая информация
Пример строки:
Starting DemoApplication using Java 21 on LAPTOP with PID 4523
Отображает главный класс, версию Java и PID процесса.
3. Активные профили
Если видишь:
The following profiles are active: dev
Значит, загружается
4. Инициализация ApplicationContext
Spring создаёт
Пример лога:
Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
5. Фаза автоконфигурации
Spring Boot подхватывает
Пример:
Tomcat initialized with port(s): 8080 (http)
Хочешь увидеть детали — запускай с флагом
6. Создание и инициализация бинов
Типичный лог:
Initializing Spring DispatcherServlet 'dispatcherServlet'
Это значит, что веб-слой готов принимать запросы.
7. Запуск веб-сервера
В зависимости от стека:
- Tomcat — для Spring MVC
- Netty — для WebFlux
Пример:
Tomcat started on port(s): 8080 (http) with context path ''
8. Метрики старта
Spring Boot 3.x добавил
9. Приложение готово
Финальный лог:
Started DemoApplication in 2.345 seconds (JVM running for 2.789)
Контекст полностью загружен, приложение работает.
Как посмотреть всё в реальном времени
Запусти приложение с флагом
java -jar app.jar --debug
Ты получишь детализированный отчёт об автоконфигурации и последовательности запуска — удобно для отладки и понимания, что реально происходит при старте.
👉 Java Portal
Когда запускаешь Spring Boot и в консоли пролетают тонны логов - вот что это всё значит:
1. Spring Boot Banner
Сначала появляется ASCII-баннер с версией Spring Boot:
:: Spring Boot :: (v3.3.4)
Он показывает версию приложения и данные JVM.
2. Стартовая информация
Пример строки:
Starting DemoApplication using Java 21 on LAPTOP with PID 4523
Отображает главный класс, версию Java и PID процесса.
3. Активные профили
Если видишь:
The following profiles are active: dev
Значит, загружается
application-dev.yml — удобно для конфигов под разные окружения.4. Инициализация ApplicationContext
Spring создаёт
ApplicationContext, сканирует компоненты, конфигурации и автоконфигурации.Пример лога:
Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
5. Фаза автоконфигурации
Spring Boot подхватывает
AutoConfiguration-классы и автоматически связывает бины.Пример:
Tomcat initialized with port(s): 8080 (http)
Хочешь увидеть детали — запускай с флагом
--debug или --trace.6. Создание и инициализация бинов
Типичный лог:
Initializing Spring DispatcherServlet 'dispatcherServlet'
Это значит, что веб-слой готов принимать запросы.
7. Запуск веб-сервера
В зависимости от стека:
- Tomcat — для Spring MVC
- Netty — для WebFlux
Пример:
Tomcat started on port(s): 8080 (http) with context path ''
8. Метрики старта
Spring Boot 3.x добавил
StartupStep-метрики, чтобы отслеживать, на что уходит время при старте (видно, если включён Actuator).9. Приложение готово
Финальный лог:
Started DemoApplication in 2.345 seconds (JVM running for 2.789)
Контекст полностью загружен, приложение работает.
Как посмотреть всё в реальном времени
Запусти приложение с флагом
--debug:java -jar app.jar --debug
Ты получишь детализированный отчёт об автоконфигурации и последовательности запуска — удобно для отладки и понимания, что реально происходит при старте.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤6
Проект, который я советую каждому разработчику сделать хотя бы раз, написать свой парсер JSON, который превращает строку в нативный объект языка, например словарь.
Формат JSON настолько привычен, что мы просто пользуемся готовыми парсерами и редко задумываемся, как они устроены внутри. Вот основные шаги, если хочешь собрать такой парсер с нуля:
Разобраться со спецификацией JSON.
Написать токенайзер, который выделяет токены из строки (можно использовать Lex).
Определить грамматику JSON по спецификации с помощью Yacc.
Реализовать обработку ошибок, красивый вывод и указание позиции ошибки в строке.
Собрать нативный объект языка — словарь, hashmap и т.д.
Прогнать реализацию на тестах, чтобы убедиться в корректности.
Если хочешь усложнить задачу — не используй Lex и Yacc, а напиши токенайзер и парсер полностью вручную, специально под JSON, без универсальности.
Сделав такой проект, ты не только поймёшь, как работает JSON, но и:
почему его парсинг считается относительно медленным и затратным
как устроена стадия парсинга в любом компиляторе
насколько всё это интересно, если копнуть глубже
Этот проект реально прокачает твои навыки решения задач. Если решишься, то желаю удачи!
👉 Java Portal
Формат JSON настолько привычен, что мы просто пользуемся готовыми парсерами и редко задумываемся, как они устроены внутри. Вот основные шаги, если хочешь собрать такой парсер с нуля:
Разобраться со спецификацией JSON.
Написать токенайзер, который выделяет токены из строки (можно использовать Lex).
Определить грамматику JSON по спецификации с помощью Yacc.
Реализовать обработку ошибок, красивый вывод и указание позиции ошибки в строке.
Собрать нативный объект языка — словарь, hashmap и т.д.
Прогнать реализацию на тестах, чтобы убедиться в корректности.
Если хочешь усложнить задачу — не используй Lex и Yacc, а напиши токенайзер и парсер полностью вручную, специально под JSON, без универсальности.
Сделав такой проект, ты не только поймёшь, как работает JSON, но и:
почему его парсинг считается относительно медленным и затратным
как устроена стадия парсинга в любом компиляторе
насколько всё это интересно, если копнуть глубже
Этот проект реально прокачает твои навыки решения задач. Если решишься, то желаю удачи!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12😁5👍2💊2🤔1
Большинство разработчиков пользуются всего парой Git команд.
Вот еще 15, которые сэкономят вам кучу времени.
👉 Java Portal
Вот еще 15, которые сэкономят вам кучу времени.
git stash → Сохранить работу без коммита. Можно прыгать по веткам, не теряя правки.
git reflog → Находит потерянные коммиты. Спасательный круг, если что-то пошло не так с git reset.
git bisect → Двоичный поиск по коммитам, чтобы вычислить баг. Гораздо быстрее ручной проверки.
git rebase -i → Причесывает историю перед пушем. Сквош, перестановка или правка коммитов.
git cherry-pick → Применяет нужные коммиты в другую ветку. Без полноценного merge.
git diff --staged → Показывает, что именно пойдет в коммит. Помогает поймать косяки заранее.
git commit --amend → Поправить последний коммит или добавить забытые файлы.
git reset HEAD~1 → Откатывает последний коммит, но оставляет изменения. Начинаешь заново, ничего не теряя.
git clean -fd → Удаляет все неотслеживаемые файлы и папки. Полная очистка, когда нужно начать на чистую.
git log --oneline --graph → Компактная визуализация истории. Ветки и слияния видно как на ладони.
git blame → Показывает, кто и когда писал каждую строку. Удобно искать момент появления бага.
git show → Детальная инфа по любому коммиту. И изменения, и метаданные.
git remote -v → Список всех удаленных репозиториев. Полезно, чтобы проверить, куда вы пушите.
git fetch --prune → Обновляет информацию о ремоутах и удаляет устаревшие ветки.
git diff branch1..branch2 → Сравнивает две ветки. Видно, что именно в них различается.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤5
Подсказка по Java: начиная с Java 9 можно использовать
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Вместо:
Вы можете сделать следующее:
👉 Java Portal
Stream.takeWhile() для удобного «нарезания» списков через стримы. Это простой способ взять элементы, пока выполняется нужное условие, без лишнего кода.List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Вместо:
List<Integer> result = new ArrayList<>();
for (Integer n : numbers) {
if (n < 5) {
result.add(n);
} else {
break;
}
}
System.out.println(result); // [1, 2, 3, 4]
Вы можете сделать следующее:
result = numbers.stream()
.takeWhile(n -> n < 5)
.toList();
System.out.println(result); // [1, 2, 3, 4]
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21❤8
Парень собрал репозиторий, чтобы показать новые встроенные возможности отказоустойчивости в Spring Framework 7. Никаких дополнительных зависимостей вроде spring-retry — все уже под капотом 🤯
Можно использовать декларативную аннотацию
Можно написать свой
Нужен больше контроля — бери
Хочешь ограничить число одновременных подключений — используй
👉 Java Portal
Можно использовать декларативную аннотацию
Retry, чтобы настроить, как и когда нужно повторять выполнение Можно написать свой
listener, чтобы получить наблюдаемость за разными событиями.Нужен больше контроля — бери
RetryTemplate Хочешь ограничить число одновременных подключений — используй
ConcurrentPlease open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥6
Мы охотились за лишними 300 мс задержки в микросервисе. Думали, что это сборщик мусора в Java.
Два дня крутили настройки JVM. Ноль эффекта.
А настоящая проблема оказалась в git clone внутри init-контейнера.
Сервис случайно настроили так, что он на каждом старте клонировал репозиторий ради одного конфиг-файла.
Клонирование было медленным, но задержка терялась на фоне общего старта приложения.
Сервис не тормозил - он просто постоянно перезапускался.
Всегда проверяйте сайдкары и init-контейнеры раньше, чем лезете в логику приложения.
👉 Java Portal
Два дня крутили настройки JVM. Ноль эффекта.
А настоящая проблема оказалась в git clone внутри init-контейнера.
Сервис случайно настроили так, что он на каждом старте клонировал репозиторий ради одного конфиг-файла.
Клонирование было медленным, но задержка терялась на фоне общего старта приложения.
Сервис не тормозил - он просто постоянно перезапускался.
Всегда проверяйте сайдкары и init-контейнеры раньше, чем лезете в логику приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥3🏆3❤1
IntelliJ IDEA начнет использовать JSpecify как основную null-safe библиотеку начиная с версии 2025.3.
"Переход на JSpecify это хороший пример того, как совместная работа в экосистеме Java приводит не просто к очередному стандарту, а к тому, который реально приносит пользу разработчикам."
👉 Java Portal
"Переход на JSpecify это хороший пример того, как совместная работа в экосистеме Java приводит не просто к очередному стандарту, а к тому, который реально приносит пользу разработчикам."
Please open Telegram to view this post
VIEW IN TELEGRAM
Null-safe applications with Spring Boot 4
Level up your Java code and explore what Spring can do for you.
❤5👍4
Многие ненавидят Java не потому что язык плохой, а потому что первое знакомство с ним вышло травматичным.
В универе его чаще всего преподавали на примерах из прошлого века, а преподаватели были больше заняты тем, чтобы сто раз написать public static void main, чем объяснить, почему всё устроено именно так. А ещё эта многословность, ошибки компиляции, необходимость сходу понимать классы, объекты, наследование… неудивительно, что после такой встречи у людей остаётся отвращение.
Плюс порог входа у Java выше, чем у более дружелюбных языков вроде Python или JavaScript. И хотя это уже давно не тот тормозной тяжёлый язык из 2000-х, многие до сих пор думают о нем именно так, не замечая, что сегодня он работает почти во всех крупных системах.
И тут самое забавное: пока в интернете его поливают грязью, компании всё так же активно ищут Java-разработчиков и платят им очень хорошие деньги. Потому что в реальном мире остаётся то, что работает и масштабируется.
👉 Java Portal
В универе его чаще всего преподавали на примерах из прошлого века, а преподаватели были больше заняты тем, чтобы сто раз написать public static void main, чем объяснить, почему всё устроено именно так. А ещё эта многословность, ошибки компиляции, необходимость сходу понимать классы, объекты, наследование… неудивительно, что после такой встречи у людей остаётся отвращение.
Плюс порог входа у Java выше, чем у более дружелюбных языков вроде Python или JavaScript. И хотя это уже давно не тот тормозной тяжёлый язык из 2000-х, многие до сих пор думают о нем именно так, не замечая, что сегодня он работает почти во всех крупных системах.
И тут самое забавное: пока в интернете его поливают грязью, компании всё так же активно ищут Java-разработчиков и платят им очень хорошие деньги. Потому что в реальном мире остаётся то, что работает и масштабируется.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤26
Совет по Java: можно использовать
Обычный способ:
Через joining:
👉 Java Portal
Collectors.joining(", ") чтобы собрать Stream в строку с разделителем запятая (или любым другим, если нужно).Обычный способ:
List<String> items = List.of("a", "b", "c");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
sb.append(items.get(i));
if (i < items.size() - 1) {
sb.append(", ");
}
}
System.out.println(sb.toString());Через joining:
List<String> items = List.of("a", "b", "c");
String result = items.stream().collect(Collectors.joining(", "));
System.out.println(result.toString());Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍3
API VERSIONING позволяет разработчикам поддерживать несколько версий эндпоинтов веб-сервиса (например, /users или /products), не ломая интеграции у клиентов при внесении изменений.
В новом Spring Boot 4 появилась встроенная поддержка версионирования API, и настраивается она очень просто.
→ Добавь строки в конфиг (
1 способ: версионирование через заголовок
(Клиент передает версию в header, например: api-version: 1 — название заголовка можно выбрать любое)
2 способ: версионирование через query-параметр
(Клиент передает версию в запросе, например: ?version=1)
→ Установка версии по умолчанию
(Используется версия 1.0, если клиент ничего не указал)
Примечание: если версия указана и в заголовке, и в query-параметре, то приоритет у более высокой версии. Например, header = 2, query = 1 → в итоге будет 2.
Готово.
a) Без множества контроллеров
b) Без /v1/, /v2/ в URL
c) Код чище и проще поддерживать
👉 Java Portal
В новом Spring Boot 4 появилась встроенная поддержка версионирования API, и настраивается она очень просто.
→ Добавь строки в конфиг (
application.properties) под твой сценарий. Можно использовать оба варианта одновременно — заголовки и query-параметры.1 способ: версионирование через заголовок
(Клиент передает версию в header, например: api-version: 1 — название заголовка можно выбрать любое)
spring.mvc.apiversion.use.header = api-version
2 способ: версионирование через query-параметр
(Клиент передает версию в запросе, например: ?version=1)
spring.mvc.apiversion.use.query-parameter = version
→ Установка версии по умолчанию
(Используется версия 1.0, если клиент ничего не указал)
spring.mvc.apiversion.default = 1.0
Примечание: если версия указана и в заголовке, и в query-параметре, то приоритет у более высокой версии. Например, header = 2, query = 1 → в итоге будет 2.
Готово.
a) Без множества контроллеров
b) Без /v1/, /v2/ в URL
c) Код чище и проще поддерживать
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥7❤2
Spring Boot: на этапе разработки можно включить spring.main.lazy-initialization=true, чтобы ускорить запуск приложения.
По умолчанию Spring Boot инициализирует все бины при старте. В среде разработки это приводит к:
Более долгому старту приложения, особенно в крупных проектах
Приходится ждать загрузки бинов, которые прямо сейчас даже не нужны
Чтобы избежать этого, в
Важно сохранить поведение по умолчанию в проде, потому что:
Ошибки на старте выявляются раньше
Все компоненты готовы принимать запросы сразу
👉 Java Portal
По умолчанию Spring Boot инициализирует все бины при старте. В среде разработки это приводит к:
Более долгому старту приложения, особенно в крупных проектах
Приходится ждать загрузки бинов, которые прямо сейчас даже не нужны
Чтобы избежать этого, в
application.properties укажите:spring.main.lazy-initialization=true
Важно сохранить поведение по умолчанию в проде, потому что:
Ошибки на старте выявляются раньше
Все компоненты готовы принимать запросы сразу
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍5
19 ноября(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
25 золотых правил системного дизайна
👉 Java Portal
1. Система с упором на чтение
> Используй кэш (Redis/Memcached) для частых запросов вроде профилей пользователей
2. Низкая задержка
> Используй кэш и CDN (Cloudflare), чтобы раздавать статику ближе к пользователю
3. Система с упором на запись
> Используй Message Queue (Kafka) для буферизации большого объема записей (логи, аналитика)
4. ACID-требования
> Используй SQL (PostgreSQL) для строгих транзакций вроде банковских операций
5. Неструктурированные данные
> Используй NoSQL (MongoDB) для гибких схем, например каталогов товаров
6. Сложные медиа-ресурсы
> Используй Blob Storage (AWS S3) для видео, изображений и больших файлов
7. Сложные предварительные расчёты
> Используй Message Queue + Cache для асинхронной генерации контента (например ленты новостей)
8. Поиск при больших объемах данных
> Используй Elasticsearch для полнотекстового поиска и автокомплита
9. Масштабирование SQL
> Используй шардирование, чтобы разделить большие таблицы на несколько инстансов
10. Высокая доступность
> Используй Load Balancer (NGINX) чтобы распределять трафик и избегать перегрузки
11. Глобальная доставка данных
> Используй CDN для стабильного стриминга и раздачи контента по всему миру
12. Графовые данные
> Используй Graph DB (Neo4j) для соцсетей, рекомендаций и связей между сущностями
13. Масштабирование компонентов
> Используй горизонтальное масштабирование, а не просто апгрейд железа
14. Быстрые запросы к базе
> Используй индексы на ключевых колонках вроде email или user_id
15. Пакетные задачи
> Используй Batch Processing для отчётов, расчётов или периодических задач
16. Защита от злоупотреблений
> Используй Rate Limiter, чтобы предотвращать DDoS и спам запросов к API
17. Доступ к микросервисам
> Используй API Gateway для авторизации, маршрутизации и SSL-терминации
18. Единая точка отказа
> Добавляй Redundancy (Active-Passive), чтобы сервис продолжал работать при сбоях
19. Отказоустойчивость данных
> Используй репликацию (Master-Slave), чтобы данные не терялись при падении узлов
20. Реальное время
> Используй WebSockets для чатов, лайв-обновлений, лайв-результатов
21. Обнаружение сбоев
> Используй Heartbeat-пинг, чтобы проверять статус сервисов каждые несколько секунд
22. Целостность данных
> Используй Checksums (MD5/SHA) чтобы проверить, что загруженные файлы не повреждены
23. Децентрализованное состояние
> Используй Gossip Protocol, чтобы ноды обменивались статусами без центрального сервера
24. Эффективное кеширование
> Используй Consistent Hashing, чтобы добавлять или убирать кэш-ноды без полного пересчёта ключей
25. Работа с геоданными
> Используй Quadtree или Geohash для быстрых запросов вроде поиска ближайших водителей
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
12 рекомендаций по дизайну API для бэкенд-разработчиков
(Их часто спрашивают на собеседованиях)
1. Понятные имена ресурсов
2. Корректное использование HTTP-методов
-
-
-
-
3. Идемпотентность
Клиент отправляет:
Если запрос повторится, сервер должен вернуть тот же результат, не создавая операцию заново.
4. Версионирование API
Рекомендуемый вариант — в URL:
5. Правильные статус-коды
Если пользователь не найден:
6. Пагинация
Пример:
Ответ должен содержать элементы 51–100.
7. Фильтрация и сортировка
Пример:
8. Безопасность
Использование JWT в заголовках:
9. Rate limiting
Например: 100 запросов в минуту.
После превышения — вернуть:
10. Кэширование
Запрос:
Ответ содержит:
Повторный запрос:
Если не изменилось — 304 Not Modified.
11. Документация
Используй:
- Swagger UI
- OpenAPI
Разработчики должны видеть схемы, параметры и иметь возможность тестировать запросы.
12. Быть прагматичным
Иногда лучше так:
чем строго REST-подход:
Хороший API читается как логичная, предсказуемая система и экономит время всем, кто с ним работает.
👉 Java Portal
(Их часто спрашивают на собеседованиях)
1. Понятные имена ресурсов
❌`GET /get-all-orders`
✅`GET /orders`
2. Корректное использование HTTP-методов
-
POST /users — создать пользователя -
GET /users/123 — получить пользователя -
PUT /users/123 — заменить полностью -
DELETE /users/123 — удалить 3. Идемпотентность
Клиент отправляет:
POST /payments
Idempotency-Key: abc-123
Если запрос повторится, сервер должен вернуть тот же результат, не создавая операцию заново.
4. Версионирование API
Рекомендуемый вариант — в URL:
GET /v1/products/42
GET /v2/products/42
5. Правильные статус-коды
Если пользователь не найден:
❌ `200 OK { "error": "user not found" }`
✅ `404 Not Found`6. Пагинация
Пример:
GET /articles?page=2&limit=50
Ответ должен содержать элементы 51–100.
7. Фильтрация и сортировка
Пример:
GET /orders?status=shipped&sort=-created_at
8. Безопасность
Использование JWT в заголовках:
Authorization: Bearer <token>
9. Rate limiting
Например: 100 запросов в минуту.
После превышения — вернуть:
429 Too Many Requests
10. Кэширование
Запрос:
GET /blog/posts/123
Ответ содержит:
ETag: "abc"
Повторный запрос:
If-None-Match: "abc"
Если не изменилось — 304 Not Modified.
11. Документация
Используй:
- Swagger UI
- OpenAPI
Разработчики должны видеть схемы, параметры и иметь возможность тестировать запросы.
12. Быть прагматичным
Иногда лучше так:
POST /auth/login
чем строго REST-подход:
POST /sessions
Хороший API читается как логичная, предсказуемая система и экономит время всем, кто с ним работает.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥4❤2