🚀 Spring Boot: не отдавайте JPA Entity напрямую в API - используйте DTO на границах
Если возвращать Entity из контроллера, вы жёстко связываете API с внутренней моделью базы. Любое изменение в persistence-слое может сломать внешний контракт.
DTO решает сразу несколько проблем:
• API становится независимым от слоя данных
• Избегаете ошибок LazyInitializationException
• Не утечёт лишняя информация (например, password, internalNote)
• Улучшается безопасность и контроль над тем, что видит клиент
Идея простая:
Entity - для базы
DTO - для API
Конвертируйте Entity → DTO в сервисе или через mapper (MapStruct / manual mapping).
Чистые границы = стабильный API и меньше багов.
#SpringBoot #Java #Backend #SoftwareEngineer
Если возвращать Entity из контроллера, вы жёстко связываете API с внутренней моделью базы. Любое изменение в persistence-слое может сломать внешний контракт.
DTO решает сразу несколько проблем:
• API становится независимым от слоя данных
• Избегаете ошибок LazyInitializationException
• Не утечёт лишняя информация (например, password, internalNote)
• Улучшается безопасность и контроль над тем, что видит клиент
Идея простая:
Entity - для базы
DTO - для API
Конвертируйте Entity → DTO в сервисе или через mapper (MapStruct / manual mapping).
Чистые границы = стабильный API и меньше багов.
#SpringBoot #Java #Backend #SoftwareEngineer
❤10👍5🥰2
Если вы используете Hibernate, добавьте:
spring.jpa.hibernate.ddl-auto=validateЧто это даёт:
- Приложение проверяет, совпадает ли схема БД с entity
- Если есть расхождения — сервис не запустится
- Никаких случайных изменений структуры в продакшене
Идеальный сценарий - использовать вместе с Flyway или Liquibase:
spring.jpa.hibernate.ddl-auto=validate
spring.flyway.enabled=true
Что в итоге:
- Все изменения БД — только через migration-скрипты
- Fail fast, если схема и код не совпадают
- Меньше сюрпризов после деплоя
Это один из тех параметров, которые могут спасти продакшен от тихих и очень дорогих ошибок.
#SpringBoot #JavaDev
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍4🔥4
В распределённых системах ошибки — это норма:
* внешние сервисы падают
* запросы зависают
* API начинают тормозить
* нагрузка резко растёт
Если не контролировать такие ситуации, один нестабильный сервис может «уронить» всю систему.
Resilience4j решает эту проблему с помощью набора паттернов отказоустойчивости.
Основные компоненты:
Circuit Breaker
Отслеживает частоту ошибок и временно блокирует обращения к нестабильному сервису, чтобы дать ему восстановиться.
Rate Limiter
Ограничивает количество запросов и защищает систему от перегрузки.
Retry
Автоматически повторяет запросы при временных сбоях, с настройкой числа попыток и интервалов.
Bulkhead
Ограничивает количество параллельных вызовов или потоков, чтобы сбой в одной части не заблокировал ресурсы всей системы.
TimeLimiter
Устанавливает таймауты выполнения, чтобы не ждать слишком долго ответы от внешних сервисов.
Почему это важно:
В микросервисной архитектуре надёжность — это не отсутствие ошибок,
а способность системы правильно на них реагировать.
Resilience4j — лёгкая, модульная библиотека с лицензией Apache-2.0, которая помогает строить стабильные и предсказуемые распределённые системы.
https://github.com/resilience4j/resilience4j
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤3
⚠️ Spring Boot: не включайте publish-request-params в production
В Spring Boot есть настройка:
spring.mvc.publish-request-params=true
Она включает логирование параметров HTTP-запросов.
Это удобно в dev-среде, потому что можно видеть:
• request headers
• query parameters
• form data
Обычно это используют вместе с фильтром:
Но есть важная проблема.
В production такие логи могут случайно сохранить чувствительные данные пользователей.
Например:
Если включено логирование payload, такие данные могут попасть в:
• application logs
• log-агрегаторы
• мониторинг системы
А это уже серьёзная уязвимость безопасности.
Поэтому правило простое:
- включайте
- никогда не логируйте
- маскируйте чувствительные поля (`password`,
Маленькая настройка -
но может привести к утечке данных.
#SpringBoot #Java #Backend #Security
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
В Spring Boot есть настройка:
spring.mvc.publish-request-params=true
Она включает логирование параметров HTTP-запросов.
Это удобно в dev-среде, потому что можно видеть:
• request headers
• query parameters
• form data
Обычно это используют вместе с фильтром:
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludeHeaders(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(1000);
filter.setAfterMessagePrefix("COMPLETE REQUEST: ");
return filter;
}
Но есть важная проблема.
В production такие логи могут случайно сохранить чувствительные данные пользователей.
Например:
POST /login
{
"username": "john",
"password": "mypassword"
}
Если включено логирование payload, такие данные могут попасть в:
• application logs
• log-агрегаторы
• мониторинг системы
А это уже серьёзная уязвимость безопасности.
Поэтому правило простое:
- включайте
publish-request-params только в dev - никогда не логируйте
request body в production - маскируйте чувствительные поля (`password`,
token, `authorization`)Маленькая настройка -
но может привести к утечке данных.
#SpringBoot #Java #Backend #Security
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
❤7👍6🔥2
☕ Java Tip: рекурсивный обход файловой системы
В Java есть удобный способ рекурсивно обойти все файлы в директории - метод
Он возвращает Stream<Path>, что позволяет легко фильтровать и обрабатывать файлы через Stream API.
Пример - найти все
Что происходит:
• Files.walk(startPath) - рекурсивно проходит по всем папкам
• filter(Files::isRegularFile) - оставляет только файлы
• endsWith(".java") - фильтр по расширению
• forEach - обработка найденных файлов
Это намного чище, чем писать собственную рекурсивную функцию обхода директорий.
#Java #JavaDev #Programming
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
В Java есть удобный способ рекурсивно обойти все файлы в директории - метод
Files.walk().Он возвращает Stream<Path>, что позволяет легко фильтровать и обрабатывать файлы через Stream API.
Пример - найти все
.java файлы в папке src:
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Path startPath = Paths.get("src");
try (Stream<Path> paths = Files.walk(startPath)) {
paths
.filter(Files::isRegularFile)
.filter(path -> path.toString().endsWith(".java"))
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Что происходит:
• Files.walk(startPath) - рекурсивно проходит по всем папкам
• filter(Files::isRegularFile) - оставляет только файлы
• endsWith(".java") - фильтр по расширению
• forEach - обработка найденных файлов
Это намного чище, чем писать собственную рекурсивную функцию обхода директорий.
#Java #JavaDev #Programming
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
❤4👍2🔥2
☕ Java совет: сравнение времени без ловушек точности
Иногда при сравнении времени в Java проверки равенства могут неожиданно падать, потому что значения отличаются на миллисекунды или наносекунды.
Например:
Если сравнивать напрямую, они разные.
Но если вам важна точность до минуты, это можно легко исправить.
Используйте Instant.truncatedTo():
Метод truncatedTo() обрезает время до нужной точности:
• ChronoUnit.MINUTES
• ChronoUnit.HOURS
• ChronoUnit.DAYS
Это помогает избежать проблем, когда значения отличаются только в миллисекундах или наносекундах.
Полезно для:
• логов
• временных окон
• аналитики
• дедупликации событий
Маленький приём —
но часто спасает от неочевидных багов в time-логике.
#Java #JavaDev #Backend #Programming
⚡️ Полезные ресурсы по Java 🚀 Max
@java_library
Иногда при сравнении времени в Java проверки равенства могут неожиданно падать, потому что значения отличаются на миллисекунды или наносекунды.
Например:
Instant a = Instant.parse("2025-10-01T10:42:11Z");
Instant b = Instant.parse("2025-10-01T10:42:44Z");
Если сравнивать напрямую, они разные.
Но если вам важна точность до минуты, это можно легко исправить.
Используйте Instant.truncatedTo():
boolean sameMinute =
a.truncatedTo(ChronoUnit.MINUTES)
.equals(b.truncatedTo(ChronoUnit.MINUTES));
System.out.println(sameMinute); // true
Метод truncatedTo() обрезает время до нужной точности:
• ChronoUnit.MINUTES
• ChronoUnit.HOURS
• ChronoUnit.DAYS
Это помогает избежать проблем, когда значения отличаются только в миллисекундах или наносекундах.
Полезно для:
• логов
• временных окон
• аналитики
• дедупликации событий
Маленький приём —
но часто спасает от неочевидных багов в time-логике.
#Java #JavaDev #Backend #Programming
⚡️ Полезные ресурсы по Java 🚀 Max
@java_library
❤3👍3🔥1
PipedOutputStream
Он работает совместно с
Это позволяет организовать обмен данными между потоками по принципу "производитель-потребитель".
Для связи
Метод
Он часто используется для подключения вывода одного потока к вводу другого.
#это_база
PipedOutputStream используется для организации потоковой передачи данных между потоками.Он работает совместно с
PipedInputStream. Один поток записывает данные в PipedOutputStream, а другой считывает их из соответствующего PipedInputStream. Это позволяет организовать обмен данными между потоками по принципу "производитель-потребитель".
Для связи
PipedOutputStream и PipedInputStream нужно использовать метод connect(). Метод
write() используется для записи данных, как и в обычных потоках вывода.PipedOutputStream полезен, когда нужен простой способ организовать обмен данными между потоками в одной программе.Он часто используется для подключения вывода одного потока к вводу другого.
#это_база
❤4👍3
🔥 Полезная подборка каналов только код, практика и самые передовые инструменты, которые используют разработчики прямо сейчас.👇
🖥 ИИ: t.me/ai_machinelearning_big_data
🖥 Python: t.me/pythonl
🖥 Linux: t.me/linuxacademiya
🖥 C++ t.me/cpluspluc
🖥 Docker: t.me/DevopsDocker
🖥 Хакинг: t.me/linuxkalii
🖥 Devops: t.me/DevOPSitsec
👣 Golang: t.me/Golang_google
🖥 Аналитика: t.me/data_analysis_ml
🖥 Javascript: t.me/javascriptv
🖥 C#: t.me/csharp_ci
🖥 Java: t.me/javatg
🖥 Базы данных: t.me/sqlhub
👣 Rust: t.me/rust_code
🤖 Технологии: t.me/vistehno
💰 Экономика и инвестиции в ИИ t.me/financeStable
💼 Актуальные вакансии: t.me/addlist/_zyy_jQ_QUsyM2Vi
🖥 Подборка по Golang: https://t.me/addlist/MUtJEeJSxeY2YTFi
⚡️ Лучшие ИИ ресурсы: https://t.me/addlist/2Ls-snqEeytkMDgy
Max ИИ: https://max.ru/ai_machinelearning_big_data
Max Ml: https://max.ru/vistehno
Max python: https://max.ru/pythonl
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Max Java: https://max.ru/javatg
Max Sql: https://max.ru/sqlhub
Max Devops: https://max.ru/DevOPSitsec
Анализ данных: https://max.ru/data_analysis_ml
C++ : https://max.ru/cpluspluc
C#: https://max.ru/csharp_ci
🖥 Chatgpt бот в тг: t.me/Chatgpturbobot
📚 Бесплатные ит-книги: https://t.me/addlist/HwywK4fErd8wYzQy
💰 Экономика и инвестиции в ИИ t.me/financeStable
💼 Актуальные вакансии: t.me/addlist/_zyy_jQ_QUsyM2Vi
⚡️ Лучшие ИИ ресурсы: https://t.me/addlist/2Ls-snqEeytkMDgy
Max ИИ: https://max.ru/ai_machinelearning_big_data
Max Ml: https://max.ru/vistehno
Max python: https://max.ru/pythonl
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Max Java: https://max.ru/javatg
Max Sql: https://max.ru/sqlhub
Max Devops: https://max.ru/DevOPSitsec
Анализ данных: https://max.ru/data_analysis_ml
C++ : https://max.ru/cpluspluc
C#: https://max.ru/csharp_ci
📚 Бесплатные ит-книги: https://t.me/addlist/HwywK4fErd8wYzQy
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥2
Forwarded from Java
🚀 Java 26 стала умнее — особенно в pattern matching
Теперь работа с pattern matching выражениями стала заметно стабильнее и предсказуемее
Что улучшили:
🟢 Более надёжный type inference
компилятор лучше понимает типы в сложных условиях
🟢 Меньше edge-case ошибок
меньше неожиданных падений и предупреждений
🟢 Консистентное поведение
одинаковая логика в if и switch
Что это даёт на практике:
раньше при усложнении условий
компилятор мог “теряться”
теперь:
- анализ потока стал умнее
- переменные из pattern matching корректно распознаются
- код становится чище и безопаснее
Java становится всё ближе к современным языкам
с удобным и предсказуемым контролем типов
#Java #JavaDev
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
Теперь работа с pattern matching выражениями стала заметно стабильнее и предсказуемее
Что улучшили:
🟢 Более надёжный type inference
компилятор лучше понимает типы в сложных условиях
🟢 Меньше edge-case ошибок
меньше неожиданных падений и предупреждений
🟢 Консистентное поведение
одинаковая логика в if и switch
Что это даёт на практике:
раньше при усложнении условий
компилятор мог “теряться”
теперь:
- анализ потока стал умнее
- переменные из pattern matching корректно распознаются
- код становится чище и безопаснее
Java становится всё ближе к современным языкам
с удобным и предсказуемым контролем типов
#Java #JavaDev
⚡️ Полезные ресурсы по Java 🚀 Max
@javatg
❤5👍1🔥1
🚀 Spring Boot: не делай эту ошибку с filters / interceptors
Многие используют фильтры и интерцепторы неправильно 👇
👉 Они должны быть только для cross-cutting задач
(то, что применяется ко ВСЕМ запросам)
Примеры нормального использования:
🟢 Filters:
- CORS
- Encoding
🟢 Interceptors:
- аутентификация / авторизация
- метрики / логирование
- locale
- общие headers
❌ Главная ошибка:
кладут туда бизнес-логику
Например:
- запрос в БД
- проверка подписки
- сложная логика
Почему это плохо:
- выполняется на КАЖДЫЙ запрос
- создаёт лишнюю нагрузку
- ломает архитектуру
- усложняет тестирование
📉 Итог:
interceptor превращается в «мусорный слой»
💡 Как правильно:
- бизнес-логика → в сервисах
- контроллеры → orchestration
⚡️ Полезные ресурсы по Java 🚀 Max
Многие используют фильтры и интерцепторы неправильно 👇
👉 Они должны быть только для cross-cutting задач
(то, что применяется ко ВСЕМ запросам)
Примеры нормального использования:
🟢 Filters:
- CORS
- Encoding
🟢 Interceptors:
- аутентификация / авторизация
- метрики / логирование
- locale
- общие headers
❌ Главная ошибка:
кладут туда бизнес-логику
Например:
- запрос в БД
- проверка подписки
- сложная логика
Почему это плохо:
- выполняется на КАЖДЫЙ запрос
- создаёт лишнюю нагрузку
- ломает архитектуру
- усложняет тестирование
📉 Итог:
interceptor превращается в «мусорный слой»
💡 Как правильно:
- бизнес-логика → в сервисах
- контроллеры → orchestration
⚡️ Полезные ресурсы по Java 🚀 Max
❤6👍5🔥3
🧠 Можно ли переопределить
Нет, нельзя.
Метод
📌 Почему:
-
-
- Гарантирует, что при вызове
💡 Если хотите вернуть “свой” тип, делайте отдельный метод:
⚠️ Переопределяемый
⚡️ Полезные ресурсы по Java 🚀 Max
getClass() в Java?Нет, нельзя.
Метод
getClass() в java.lang.Object объявлен так:
public final native Class<?> getClass();
📌 Почему:
-
final — запрещает переопределение в наследниках.-
native — реализован в JVM, а не на Java.- Гарантирует, что при вызове
obj.getClass() всегда вернётся реальный класс объекта, без подмен и сюрпризов.💡 Если хотите вернуть “свой” тип, делайте отдельный метод:
class MyClass {
public String getTypeName() {
return "CustomType";
}
}
⚠️ Переопределяемый
getClass() сломал бы рефлексию, сериализацию и кучу системных механизмов. Именно поэтому Java защищает его.⚡️ Полезные ресурсы по Java 🚀 Max
❤8👍6🔥2
Приглашаем бэкенд-разработчиков на Week Offer Backend*
Такой формат позволяет пройти секции и финалы за неделю и сразу получить офер. Зарегистрироваться можно до 8 апреля, а сам ивент пройдёт с 11 по 17 апреля, онлайн.
Кого мы ищем:
🟢 Бэкенд-разработчиков c опытом работы от 4 лет на C++, Python, Java/Kotlin, Go**.
🟢 Стажёров-разработчиков c навыком кодинга на C++, Python, Java, Kotlin, Go** и базой по алгоритмам и структурам данных.
🔶 Все подробности, регистрация и материалы для подготовки доступны на сайте: https://yandex.ru/project/events/wo_backend_0426
Приходите создавать полезные продукты для миллионов пользователей!
Такой формат позволяет пройти секции и финалы за неделю и сразу получить офер. Зарегистрироваться можно до 8 апреля, а сам ивент пройдёт с 11 по 17 апреля, онлайн.
Кого мы ищем:
Приходите создавать полезные продукты для миллионов пользователей!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥1
🔥 Лучшие БЕСПЛАТНЫЕ ресурсы по Linux в 2026 году
1. Linux Foundation Training
https://training.linuxfoundation.org/training/introduction-to-linux/
2. Linux Journey
https://linuxjourney.com
3. Ubuntu Tutorials
https://ubuntu.com/tutorials
4. Red Hat Training Resources
https://developers.redhat.com/learn
5. Документация GNU
https://gnu.org/manual
6. OverTheWire Bandit (Linux-варгеймы)
https://overthewire.org/wargames
7. Книга The Linux Command Line
https://linuxcommand.org/tlcl.php
8. MIT Missing Semester (Linux и CLI)
https://missing.csail.mit.edu
9. Туториалы по Linux от DigitalOcean
https://digitalocean.com/community/tutorials
10. Linux From Scratch
https://linuxfromscratch.org
11. Arch Linux Wiki
https://wiki.archlinux.org
12. Курс по Linux от freeCodeCamp
https://freecodecamp.org/news/tag/linux
13. Linux Survival (интерактивное обучение)
https://linuxsurvival.com
14. NDG Linux Essentials
https://netacad.com/courses/os-it/ndg-linux-essentials
15. Bash Guide (руководство по Bash)
https://tldp.org/LDP/Bash-Beginners-Guide/html
1. Linux Foundation Training
https://training.linuxfoundation.org/training/introduction-to-linux/
2. Linux Journey
https://linuxjourney.com
3. Ubuntu Tutorials
https://ubuntu.com/tutorials
4. Red Hat Training Resources
https://developers.redhat.com/learn
5. Документация GNU
https://gnu.org/manual
6. OverTheWire Bandit (Linux-варгеймы)
https://overthewire.org/wargames
7. Книга The Linux Command Line
https://linuxcommand.org/tlcl.php
8. MIT Missing Semester (Linux и CLI)
https://missing.csail.mit.edu
9. Туториалы по Linux от DigitalOcean
https://digitalocean.com/community/tutorials
10. Linux From Scratch
https://linuxfromscratch.org
11. Arch Linux Wiki
https://wiki.archlinux.org
12. Курс по Linux от freeCodeCamp
https://freecodecamp.org/news/tag/linux
13. Linux Survival (интерактивное обучение)
https://linuxsurvival.com
14. NDG Linux Essentials
https://netacad.com/courses/os-it/ndg-linux-essentials
15. Bash Guide (руководство по Bash)
https://tldp.org/LDP/Bash-Beginners-Guide/html
❤5
🚀 Java - regex без боли
Нашли интересную библиотеку - Sift. Она заменяет весь этот ад с регулярками на нормальный fluent API.
Теперь вместо нечитаемых строк вида:
^[0-9a-fA-F]{6}$
Пишешь код, который реально понимаешь:
.char('#')
.then()
.exactly(6)
.hexDigits()
📌 Что это дает:
- Читаемый и понятный код
- Меньше ошибок в regex
- Быстрее разработка и поддержка
По сути — это как “переводчик” с языка регулярных выражений на человеческий Java-код.
Если когда-нибудь ломал голову над regex -это прям must-have.
#Java #JavaDev
Нашли интересную библиотеку - Sift. Она заменяет весь этот ад с регулярками на нормальный fluent API.
Теперь вместо нечитаемых строк вида:
^[0-9a-fA-F]{6}$
Пишешь код, который реально понимаешь:
.char('#')
.then()
.exactly(6)
.hexDigits()
📌 Что это дает:
- Читаемый и понятный код
- Меньше ошибок в regex
- Быстрее разработка и поддержка
По сути — это как “переводчик” с языка регулярных выражений на человеческий Java-код.
Если когда-нибудь ломал голову над regex -это прям must-have.
#Java #JavaDev
❤7👍4
⚡️ Java лайфхак: не убивай производительность боксингом
Многие даже не замечают, как теряют скорость из-за автoboxing в Stream API.
❌ Плохо (создаются объекты Integer):
Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sum = boxed.reduce(0, Integer::sum);
Каждое число → объект → лишняя память + нагрузка на GC
✅ Хорошо (работа с примитивами):
int sum = IntStream.of(1, 2, 3, 4, 5).sum();
Без лишних объектов. Быстрее. Чище.
Запомни:
- IntStream → для int
- LongStream → для long
- DoubleStream → для double
Если работаешь с числами — всегда используй primitive streams.
Это мелочь, которая на больших данных превращается в реальную экономию ресурсов.
Сохрани, чтобы не писать медленный код.
Многие даже не замечают, как теряют скорость из-за автoboxing в Stream API.
❌ Плохо (создаются объекты Integer):
Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sum = boxed.reduce(0, Integer::sum);
Каждое число → объект → лишняя память + нагрузка на GC
✅ Хорошо (работа с примитивами):
int sum = IntStream.of(1, 2, 3, 4, 5).sum();
Без лишних объектов. Быстрее. Чище.
Запомни:
- IntStream → для int
- LongStream → для long
- DoubleStream → для double
Если работаешь с числами — всегда используй primitive streams.
Это мелочь, которая на больших данных превращается в реальную экономию ресурсов.
Сохрани, чтобы не писать медленный код.
❤3👍3🔥2