🧠 10 правил безопасного Java-приложения:
1️⃣ Валидация на всех уровнях.
📌 Всегда проверяй входные данные (API, формы, запросы к БД). Используй Bean Validation (
2️⃣ Используй PreparedStatement.
⚠️ Никогда не конкатенируй SQL-запросы напрямую, чтобы избежать SQL-инъекций.
3️⃣ Не раскрывай детали исключений.
📌 Отправляй клиенту общий код ошибки, а детали логируй.
4️⃣ Скрывай конфигурацию.
💡 Используй
5️⃣ Ограничивай доступ.
📌 Spring Security — твой друг. Используй
6️⃣ Безопасная сериализация.
⚠️ Избегай Java-стандартной сериализации. Предпочитай JSON (Jackson) с явными DTO.
7️⃣ Используй актуальные версии библиотек.
📌 Регулярно проверяй зависимости (
8️⃣ Грамотно логируй.
💡 Не логируй пароли, токены и персональные данные. Используй SLF4J с Logback, настрой уровень логов.
9️⃣ Безопасные куки и заголовки.
📌 Используй атрибуты куки:
🔟 Настрой Security Headers.
📌 Используй заголовки:
*
*
*
Безопасность — это не разовая задача, а процесс 💡
👉@BookJava
1️⃣ Валидация на всех уровнях.
📌 Всегда проверяй входные данные (API, формы, запросы к БД). Используй Bean Validation (
@Valid
, @NotNull
).2️⃣ Используй PreparedStatement.
⚠️ Никогда не конкатенируй SQL-запросы напрямую, чтобы избежать SQL-инъекций.
3️⃣ Не раскрывай детали исключений.
📌 Отправляй клиенту общий код ошибки, а детали логируй.
4️⃣ Скрывай конфигурацию.
💡 Используй
application.yml
с переменными окружения для чувствительных данных (пароли, ключи API).5️⃣ Ограничивай доступ.
📌 Spring Security — твой друг. Используй
@PreAuthorize
и грамотно настраивай роли и права доступа.6️⃣ Безопасная сериализация.
⚠️ Избегай Java-стандартной сериализации. Предпочитай JSON (Jackson) с явными DTO.
7️⃣ Используй актуальные версии библиотек.
📌 Регулярно проверяй зависимости (
dependency-check
), чтобы избежать известных уязвимостей.8️⃣ Грамотно логируй.
💡 Не логируй пароли, токены и персональные данные. Используй SLF4J с Logback, настрой уровень логов.
9️⃣ Безопасные куки и заголовки.
📌 Используй атрибуты куки:
Secure
, HttpOnly
, SameSite
. Spring Security поможет тебе настроить это быстро.🔟 Настрой Security Headers.
📌 Используй заголовки:
*
X-Frame-Options: DENY
*
X-Content-Type-Options: nosniff
*
Content-Security-Policy
(CSP)Безопасность — это не разовая задача, а процесс 💡
👉@BookJava
👍11❤1
Двоичная Java: CDS, CRaC и AOT для ускорения запуска и прогрева JVM
В этой статье вы узнаете о повышении перфоманса Java-приложений. Разберём:
🔹Как работает HotSpot.
🔹Процессы исполнения байт-кода и в чём же основные проблемы.
🔹Технологии для повышения перформанса: CDS, CRaC и AOT.
🔹Два мира сборки приложений: статический и динамический.
Поговорим о двух болях, которые есть в Java-приложениях — это время запуска и время достижения пиковой производительности.
https://habr.com/ru/companies/axiomjdk/articles/911568/
👉@BookJava
В этой статье вы узнаете о повышении перфоманса Java-приложений. Разберём:
🔹Как работает HotSpot.
🔹Процессы исполнения байт-кода и в чём же основные проблемы.
🔹Технологии для повышения перформанса: CDS, CRaC и AOT.
🔹Два мира сборки приложений: статический и динамический.
Поговорим о двух болях, которые есть в Java-приложениях — это время запуска и время достижения пиковой производительности.
https://habr.com/ru/companies/axiomjdk/articles/911568/
👉@BookJava
👍2❤1
Хотите узнать, как работают алгоритмы сжатия данных?
В нашем вебинаре мы шаг за шагом создадим архиватор на Java, используя алгоритм RLE. Вы разработаете интерфейс программы и поймете, как реализовать самые эффективные методы сжатия.
Протестировав алгоритм на реальных данных, вы увидите, когда он работает наилучшим образом. Присоединяйтесь к нам и погрузитесь в мир программирования и алгоритмов!
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».
🎁
👉 Регистрация на вебинар: https://vk.cc/cMl0ID
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡1
Сегодня покажу вам интересный костыль, который до сих пор живёт в JDK и влияет на сортировку списков.
🧠 Если ты когда-нибудь пробовал сортировать LinkedList через
📌
⚠️ Но если это LinkedList (или любой не-рандом-доступ список), внутри происходит... преобразование списка в массив! Сначала все элементы копируются в массив, потом сортируются, а затем результат обратно заливается в твой список.
💡 Почему так? Сортировка напрямую через LinkedList была бы очень медленной — доступ к элементам по индексу у него O(n), а не O(1) как у ArrayList. Поэтому JDK идёт на компромисс: временная потеря памяти, но ускорение времени сортировки.
⚠️ Следствие: если у тебя большой LinkedList, сортировка будет требовать двойную память: сначала весь список копируется в массив.
Совет:
Для больших коллекций, которые часто сортируются, используй ArrayList, либо готовься к затратам памяти.
👉@BookJava
🧠 Если ты когда-нибудь пробовал сортировать LinkedList через
Collections.sort()
, знай — под капотом происходит скрытая магия.📌
Collections.sort(list)
сначала проверяет, какой это список. Если это RandomAccess-list (например, ArrayList) — используется быстрый сортировщик (TimSort) прямо по массиву.⚠️ Но если это LinkedList (или любой не-рандом-доступ список), внутри происходит... преобразование списка в массив! Сначала все элементы копируются в массив, потом сортируются, а затем результат обратно заливается в твой список.
// Да, это реально работает так:
List<Integer> list = new LinkedList<>();
// ...заполняем...
Collections.sort(list);
💡 Почему так? Сортировка напрямую через LinkedList была бы очень медленной — доступ к элементам по индексу у него O(n), а не O(1) как у ArrayList. Поэтому JDK идёт на компромисс: временная потеря памяти, но ускорение времени сортировки.
⚠️ Следствие: если у тебя большой LinkedList, сортировка будет требовать двойную память: сначала весь список копируется в массив.
Совет:
Для больших коллекций, которые часто сортируются, используй ArrayList, либо готовься к затратам памяти.
👉@BookJava
👍9🤓3
🧠 Как быстро написать компаратор в Java и не забыть про null
Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из
📌
📌
📌
💡 Такой подход краткий, читабельный и отлично работает с любыми полями, даже если они могут быть null.
⚠️ Никогда не забывай про null, особенно если сортируешь данные из БД или внешних источников. Ошибка
👉@BookJava
Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из
Comparator
:
List<User> users = ...;
users.sort(Comparator
.comparing(User::getName, Comparator.nullsLast(String::compareToIgnoreCase))
.thenComparingInt(User::getAge)
);
📌
comparing
— сравнивает по полю (например, name).📌
nullsLast
или nullsFirst
— удобно обрабатывать возможные null.📌
thenComparingInt
— дополнительная сортировка (например, по возрасту).💡 Такой подход краткий, читабельный и отлично работает с любыми полями, даже если они могут быть null.
⚠️ Никогда не забывай про null, особенно если сортируешь данные из БД или внешних источников. Ошибка
NullPointerException
во время сортировки может неожиданно прилететь в проде.👉@BookJava
👍4
Ищем Java-разработчика в команду онлайн-рекомендаций AI VK 🤖
Будем вместе разрабатывать высоконагруженные микросервисы на Java. Кроме кода доверим коллеге принимать архитектурные и технические решения, гибко настраивать ML-эксперименты и рекомендательный пайплайн.
Если любите технически сложные задачи и хотите работать с большими данными, ждём ваше резюме на сайте VK Team!
Будем вместе разрабатывать высоконагруженные микросервисы на Java. Кроме кода доверим коллеге принимать архитектурные и технические решения, гибко настраивать ML-эксперименты и рекомендательный пайплайн.
Если любите технически сложные задачи и хотите работать с большими данными, ждём ваше резюме на сайте VK Team!
🤮2
🧠 Сегодня разберём Saga — паттерн, который часто всплывает на собеседованиях уровня сеньор, особенно если речь о микросервисах.
📌 Зачем нужна Saga?
Когда нужно выполнить бизнес-операцию, затрагивающую несколько микросервисов, важно обеспечить целостность данных. Классические транзакции (
💡 Виды Saga
1. Choreography
Нет единого оркестратора. Каждый сервис реагирует на события предыдущих через очередь (Kafka, RabbitMQ).
* Простой flow
* Меньше точек отказа
2. Orchestration
Есть выделенный "оркестратор", который координирует выполнение саги, рассылая команды сервисам.
* Более явный контроль
* Лучше трассировка
⚖️ Плюсы
* Обеспечивает согласованность между сервисами
* Высокая отказоустойчивость: каждый шаг можно компенсировать
* Гибкость — легко расширять и модифицировать бизнес-логику
⚠️ Минусы
* Сложнее реализовать, чем простые транзакции
* Не моментальная консистентность — возможны временные аномалии
* Нужно проектировать compensating transactions для каждого шага
* Тяжело тестировать крайние случаи и "сорванные" шаги
🔁 Альтернативы
* Distributed Transactions (XA, 2PC) — редко используются из-за сложности и слабой поддержки в современных cloud-системах.
* Event Sourcing — другой паттерн работы с изменениями, но сложнее для чтения.
* Idempotency + Retry — иногда достаточно, если бизнес-процесс допускает.
💡 Совет: для большинства бизнес-операций с межсервисным взаимодействием, где требуется отмена — Saga остаётся самым практичным выбором. В Spring есть библиотека Axon Framework, также стоит посмотреть на Camunda.
👉@BookJava
📌 Зачем нужна Saga?
Когда нужно выполнить бизнес-операцию, затрагивающую несколько микросервисов, важно обеспечить целостность данных. Классические транзакции (
@Transactional
) тут не подходят — нет распределённого ACID. Saga решает эту проблему через последовательность локальных транзакций с возможностью отката (compensation).💡 Виды Saga
1. Choreography
Нет единого оркестратора. Каждый сервис реагирует на события предыдущих через очередь (Kafka, RabbitMQ).
* Простой flow
* Меньше точек отказа
2. Orchestration
Есть выделенный "оркестратор", который координирует выполнение саги, рассылая команды сервисам.
* Более явный контроль
* Лучше трассировка
⚖️ Плюсы
* Обеспечивает согласованность между сервисами
* Высокая отказоустойчивость: каждый шаг можно компенсировать
* Гибкость — легко расширять и модифицировать бизнес-логику
⚠️ Минусы
* Сложнее реализовать, чем простые транзакции
* Не моментальная консистентность — возможны временные аномалии
* Нужно проектировать compensating transactions для каждого шага
* Тяжело тестировать крайние случаи и "сорванные" шаги
🔁 Альтернативы
* Distributed Transactions (XA, 2PC) — редко используются из-за сложности и слабой поддержки в современных cloud-системах.
* Event Sourcing — другой паттерн работы с изменениями, но сложнее для чтения.
* Idempotency + Retry — иногда достаточно, если бизнес-процесс допускает.
💡 Совет: для большинства бизнес-операций с межсервисным взаимодействием, где требуется отмена — Saga остаётся самым практичным выбором. В Spring есть библиотека Axon Framework, также стоит посмотреть на Camunda.
👉@BookJava
👍7❤1🔥1
🧠 Сейчас расскажу о распределённых транзакциях в Java и почему их стоит использовать с осторожностью.
Когда твое приложение работает с несколькими источниками данных (например, двумя базами или базой + очередью), часто появляется соблазн обернуть всё в одну большую транзакцию с помощью JTA (Java Transaction API) и XA-ресурсов. Но на практике это почти всегда антипаттерн.
📌 Почему?
* XA-транзакции медленные и сложно отлаживаются.
* Они ломают горизонтальное масштабирование: один сбой — откат по всем участникам.
* Могут приводить к блокировкам и deadlock-ам, если инфраструктура нестабильна.
💡 Современные альтернативы:
1. Transaction outbox pattern — сначала пишем событие/задачу в outbox-таблицу в той же БД, где меняем данные, и только потом публикуем во внешний сервис.
2. Event sourcing — строим архитектуру так, чтобы любые изменения происходили через событийную модель (и проще компенсировать сбои).
3. Idempotency & retries — делаем операции идемпотентными и безопасными к повтору.
⚠️ Не используешь JTA без реальной необходимости. Spring Boot 3+ по умолчанию уже не настраивает JTA — и правильно делает.
Если всё же нужен XA:
* Используй Atomikos, Narayana или Bitronix — это современные провайдеры.
* Но всегда сначала подумай: "Могу ли я упростить архитектуру и уйти от XA?"
Пример из кода на Spring Boot:
🧠 В 99% случаев проще и надёжнее строить архитектуру вокруг событий и простых локальных транзакций, чем бороться с XA.
👉@BookJava
Когда твое приложение работает с несколькими источниками данных (например, двумя базами или базой + очередью), часто появляется соблазн обернуть всё в одну большую транзакцию с помощью JTA (Java Transaction API) и XA-ресурсов. Но на практике это почти всегда антипаттерн.
📌 Почему?
* XA-транзакции медленные и сложно отлаживаются.
* Они ломают горизонтальное масштабирование: один сбой — откат по всем участникам.
* Могут приводить к блокировкам и deadlock-ам, если инфраструктура нестабильна.
💡 Современные альтернативы:
1. Transaction outbox pattern — сначала пишем событие/задачу в outbox-таблицу в той же БД, где меняем данные, и только потом публикуем во внешний сервис.
2. Event sourcing — строим архитектуру так, чтобы любые изменения происходили через событийную модель (и проще компенсировать сбои).
3. Idempotency & retries — делаем операции идемпотентными и безопасными к повтору.
⚠️ Не используешь JTA без реальной необходимости. Spring Boot 3+ по умолчанию уже не настраивает JTA — и правильно делает.
Если всё же нужен XA:
* Используй Atomikos, Narayana или Bitronix — это современные провайдеры.
* Но всегда сначала подумай: "Могу ли я упростить архитектуру и уйти от XA?"
Пример из кода на Spring Boot:
// НЕ рекомендуется:
@EnableTransactionManagement
public class Config {
@Bean
public JtaTransactionManager transactionManager() {
return new JtaTransactionManager();
}
}
// Лучше outbox + отдельный publisher
🧠 В 99% случаев проще и надёжнее строить архитектуру вокруг событий и простых локальных транзакций, чем бороться с XA.
👉@BookJava
👍6❤1
После обучения вы сможете разрабатывать сложные Java-приложения уровня Middle+, понимать работу JVM изнутри и писать чистый, оптимизированный код.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Серия статей: «Дюк, вынеси мусор!»
Все, что нужно знать о сборке мусора в Java
🔹 Если работа с JVM для тебя не просто слова, а параметры вроде
🗂 В этой серии — подробный разбор всех современных GC, доступных в Java HotSpot VM: от базовых до самых продвинутых. Для каждого — объяснение принципов, сценарии применения, плюсы и минусы, а также практические советы по настройке.
Список статей:
1️⃣ Введение
2️⃣ Serial GC и Parallel GC
3️⃣ CMS и G1
4️⃣ ZGC
5️⃣ Epsilon GC
6️⃣ Shenandoah GC
👉@BookJava
Все, что нужно знать о сборке мусора в Java
🔹 Если работа с JVM для тебя не просто слова, а параметры вроде
Xmx
и Xms
ты прописываешь с закрытыми глазами, самое время разобраться, что же реально происходит с памятью в Java и как новые сборщики мусора могут повлиять на производительность твоего приложения.🗂 В этой серии — подробный разбор всех современных GC, доступных в Java HotSpot VM: от базовых до самых продвинутых. Для каждого — объяснение принципов, сценарии применения, плюсы и минусы, а также практические советы по настройке.
Список статей:
1️⃣ Введение
2️⃣ Serial GC и Parallel GC
3️⃣ CMS и G1
4️⃣ ZGC
5️⃣ Epsilon GC
6️⃣ Shenandoah GC
👉@BookJava
❤3👍3
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🤯2
Как не завалить приложение из-за N+1 запросов в Hibernate 🧨
N+1 проблема — больной зуб почти любого Java-разработчика. Hibernate делает жизнь проще, пока не сталкиваешься с этим 👻
📌 Суть проблемы
Допустим, у тебя есть сущности
Если пользователей 1000, то будет 1 + 1000 SQL-запросов. Это убийственно для производительности ⚠️
🛠 Как решить?
💡 Вариант 1: JOIN FETCH
Самый быстрый и простой путь — сразу подтянуть связанные сущности:
✅ Всего один SQL-запрос
❌ Может привести к дублированию строк, если связей много и они сложные
💡 Вариант 2: Entity Graph (Spring Data JPA)
Entity Graph — более гибкий подход:
✅ Удобно и понятно, нет дублей
✅ Можно легко настраивать под конкретный запрос
💡 Вариант 3: Batch fetching (настройка Hibernate)
Hibernate будет автоматически загружать связанные сущности пачками.
✅ Просто настроить и сразу эффект
❌ Всё равно несколько запросов, хотя и пачками
🧠 Когда что использовать?
▫️ JOIN FETCH — когда связи простые, а данных немного.
▫️ Entity Graph — если нужна гибкость и удобство.
▫️ Batch fetching — когда настроить проще, чем переписывать код.
Не забывай проверять SQL-запросы в логах и профилировать приложение 🔥
👉@BookJava
N+1 проблема — больной зуб почти любого Java-разработчика. Hibernate делает жизнь проще, пока не сталкиваешься с этим 👻
📌 Суть проблемы
Допустим, у тебя есть сущности
User
и связанные с ними сущности Order
. При запросе пользователей:
List<User> users = userRepository.findAll(); // Один запрос
for(User user : users) {
List<Order> orders = user.getOrders(); // +1 запрос на каждого пользователя!
}
Если пользователей 1000, то будет 1 + 1000 SQL-запросов. Это убийственно для производительности ⚠️
🛠 Как решить?
💡 Вариант 1: JOIN FETCH
Самый быстрый и простой путь — сразу подтянуть связанные сущности:
@Query("SELECT u FROM User u JOIN FETCH u.orders")
List<User> findAllWithOrders();
✅ Всего один SQL-запрос
❌ Может привести к дублированию строк, если связей много и они сложные
💡 Вариант 2: Entity Graph (Spring Data JPA)
Entity Graph — более гибкий подход:
@EntityGraph(attributePaths = {"orders"})
List<User> findAll();
✅ Удобно и понятно, нет дублей
✅ Можно легко настраивать под конкретный запрос
💡 Вариант 3: Batch fetching (настройка Hibernate)
spring.jpa.properties.hibernate.default_batch_fetch_size=20
Hibernate будет автоматически загружать связанные сущности пачками.
✅ Просто настроить и сразу эффект
❌ Всё равно несколько запросов, хотя и пачками
🧠 Когда что использовать?
▫️ JOIN FETCH — когда связи простые, а данных немного.
▫️ Entity Graph — если нужна гибкость и удобство.
▫️ Batch fetching — когда настроить проще, чем переписывать код.
Не забывай проверять SQL-запросы в логах и профилировать приложение 🔥
👉@BookJava
👍7
🚀 Подборка Telegram каналов для программистов
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
❤3
🧠 Чем Spring Native Image отличается от обычного Spring-приложения?
📌 Обычный Spring:
* Запускается на JVM, динамически загружает классы, использует рефлексию.
* Медленный старт (секунды), выше потребление памяти.
* Подходит для сложной логики с динамическим поведением (настройки, рефлексия, прокси).
📌 Spring Native Image (GraalVM):
* Компиляция в нативный бинарник.
* ⚡️ Мгновенный старт (миллисекунды), низкое потребление памяти.
* Отсутствие динамики: ограничения в рефлексии, прокси и динамической загрузке.
💡 Когда что использовать?
* Native Image — идеален для микросервисов и Serverless-приложений.
* Обычный JVM Spring — когда важна максимальная гибкость и динамика.
⚠️ Помни, что Native Image требует больше усилий по настройке и ограничений на библиотеки.
👉@BookJava
📌 Обычный Spring:
* Запускается на JVM, динамически загружает классы, использует рефлексию.
* Медленный старт (секунды), выше потребление памяти.
* Подходит для сложной логики с динамическим поведением (настройки, рефлексия, прокси).
📌 Spring Native Image (GraalVM):
* Компиляция в нативный бинарник.
* ⚡️ Мгновенный старт (миллисекунды), низкое потребление памяти.
* Отсутствие динамики: ограничения в рефлексии, прокси и динамической загрузке.
💡 Когда что использовать?
* Native Image — идеален для микросервисов и Serverless-приложений.
* Обычный JVM Spring — когда важна максимальная гибкость и динамика.
⚠️ Помни, что Native Image требует больше усилий по настройке и ограничений на библиотеки.
👉@BookJava
👍6❤4
«Я слышу свой код»: как работает Java-программист, потерявший зрение
Константин Евтеев собирает Java-код с помощью диктора NVDA, редактирует его в Блокноте и передает на Linux по SSH через самописные bash-скрипты. После потери зрения он не потерял интереса к жизни и желания быть полезным и выстроил собственную инженерную экосистему: оглавления по строкам .txt-файлами, навигация по main и маленьким методам, отладка на слух.
https://habr.com/ru/companies/axiomjdk/articles/913748/
👉@BookJava
Константин Евтеев собирает Java-код с помощью диктора NVDA, редактирует его в Блокноте и передает на Linux по SSH через самописные bash-скрипты. После потери зрения он не потерял интереса к жизни и желания быть полезным и выстроил собственную инженерную экосистему: оглавления по строкам .txt-файлами, навигация по main и маленьким методам, отладка на слух.
https://habr.com/ru/companies/axiomjdk/articles/913748/
👉@BookJava
🔥9🙏4👍1
📌 Spring Security: основная архитектура
🧠 1. SecurityFilterChain & FilterChainProxy
Spring Security строит всё вокруг цепочки фильтров (FilterChainProxy). При запросе к приложению запрос проходит через набор фильтров, каждый из которых отвечает за свой кусок логики:
* ⚙️ ChannelProcessingFilter – перенаправление на HTTPS, если нужно.
* ⚙️ SecurityContextPersistenceFilter – загружает/сохраняет
* ⚙️ UsernamePasswordAuthenticationFilter – обрабатывает форму логина (если вы используете formLogin).
* ⚙️ BasicAuthenticationFilter – поддерживает HTTP Basic (для REST).
* ⚙️ BearerTokenAuthenticationFilter (Spring Boot 3+) – для JWT/OAuth2 Bearer-токенов.
* ⚙️ ExceptionTranslationFilter – перехватывает AccessDeniedException и AuthenticationException, перенаправляет на страницу логина или возвращает 401.
* ⚙️ FilterSecurityInterceptor – проверяет, есть ли у аутентифицированного пользователя разрешение (ROLE_*) для доступа к ресурсу.
Каждый фильтр решает конкретную задачу, и порядок важен: если, например, фильтр авторизации (FilterSecurityInterceptor) стоит раньше, чем фильтр аутентификации, вы получите неожиданный отказ.
💡 Современный подход (Spring Boot 3+):
Таким образом вы сами управляете порядком фильтров и включаете только нужные.
🧠 2. AuthenticationManager & ProviderManager
Когда
📌 Совет: если нужно добавить кастомную проверку (например, MFA), реализуйте свой
🧠 3. UserDetailsService & UserDetails
🧠 4. SecurityContext & SecurityContextHolder
После успешной аутентификации фильтр устанавливает
🧠 1. SecurityFilterChain & FilterChainProxy
Spring Security строит всё вокруг цепочки фильтров (FilterChainProxy). При запросе к приложению запрос проходит через набор фильтров, каждый из которых отвечает за свой кусок логики:
* ⚙️ ChannelProcessingFilter – перенаправление на HTTPS, если нужно.
* ⚙️ SecurityContextPersistenceFilter – загружает/сохраняет
SecurityContext
(где хранится Authentication
).* ⚙️ UsernamePasswordAuthenticationFilter – обрабатывает форму логина (если вы используете formLogin).
* ⚙️ BasicAuthenticationFilter – поддерживает HTTP Basic (для REST).
* ⚙️ BearerTokenAuthenticationFilter (Spring Boot 3+) – для JWT/OAuth2 Bearer-токенов.
* ⚙️ ExceptionTranslationFilter – перехватывает AccessDeniedException и AuthenticationException, перенаправляет на страницу логина или возвращает 401.
* ⚙️ FilterSecurityInterceptor – проверяет, есть ли у аутентифицированного пользователя разрешение (ROLE_*) для доступа к ресурсу.
Каждый фильтр решает конкретную задачу, и порядок важен: если, например, фильтр авторизации (FilterSecurityInterceptor) стоит раньше, чем фильтр аутентификации, вы получите неожиданный отказ.
💡 Современный подход (Spring Boot 3+):
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth2 -> oauth2.jwt()); // JWT из OIDC/JWK
return http.build();
}
Таким образом вы сами управляете порядком фильтров и включаете только нужные.
🧠 2. AuthenticationManager & ProviderManager
Когда
UsernamePasswordAuthenticationFilter
(или другой аутентификатор) получает учётные данные, он создает UsernamePasswordAuthenticationToken
с неверифицированными (unauthenticated) флагом. Затем передаёт этот токен в AuthenticationManager
:
UsernamePasswordAuthenticationFilter → AuthenticationManager.authenticate()
AuthenticationManager
по умолчанию — это ProviderManager
, который хранит список AuthenticationProvider
(например, DaoAuthenticationProvider
для UserDetailsService или JwtAuthenticationProvider
для токенов). Каждый Provider
пытается аутентифицировать токен, и если успешно, возвращает уже аутентифицированный Authentication
с authorities.📌 Совет: если нужно добавить кастомную проверку (например, MFA), реализуйте свой
AuthenticationProvider
и зарегистрируйте его перед DaoAuthenticationProvider
.🧠 3. UserDetailsService & UserDetails
DaoAuthenticationProvider
опирается на UserDetailsService
(или ReactiveUserDetailsService
в WebFlux), чтобы получить UserDetails
(имя, пароль, роли, статус аккаунта). В Java 17+ можно пользоваться Map.of(...)
или List.of(...)
, но в реальных проектах лучше хранить в БД через JPA/Hibernate.
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository repo;
@Override
public UserDetails loadUserByUsername(String username) {
UserEntity user = repo.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return User.withUsername(user.getUsername())
.password(user.getPassword())
.authorities(user.getRoles().toArray(new String[0]))
.accountLocked(!user.isAccountNonLocked())
.build();
}
}
🧠 4. SecurityContext & SecurityContextHolder
После успешной аутентификации фильтр устанавливает
SecurityContext
в SecurityContextHolder
. По умолчанию используется стратегия MODE_THREADLOCAL
, т.е. контекст привязан к текущему потоку.
SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
🔥4
В асинхронных или веб-сервисах на реактиве нужно быть осторожным:
⚠️ Важно: не храните
🧠 5. Авторизация: FilterSecurityInterceptor & AccessDecisionManager
Если хотя бы один голос “grant”,
💡 Трюк: чтобы локально протестировать SecurityContext, можно в тестах использовать аннотацию
🧠 6. Аннотации & Method Security
Помимо URL-уровня, есть методная проверка:
* 📌
* 💡 Совет: включайте методную безопасность только там, где действительно нужна тонкая грануляция.
🧠 7. Хранение паролей & PasswordEncoder
С Java 17+ используйте
⚠️ Никогда не храните пароли в открытом виде и не используйте MD5/SHA-1 — они считаются небезопасными.
🧠 8. Stateless vs Stateful
* Stateful (Сессии): Spring создаёт HTTP-сессию, а
* Stateless (JWT/OAuth2): убираем
💡 Современный стек (Spring Boot 3+):
1. Настраиваем
2. Подключаем
3. Указываем
🧠 9. Подпись запросов & CSRF
* По умолчанию CSRF включён для “форменных” запросов (
* Если используете формы, не забудьте добавить в шаблон:
⚠️ Внимание: не отключайте CSRF, если ваше приложение использует сессии и cookie на фронтенде!
💡 Совет по отладке: включите логирование фильтров:
Тогда в логах вы увидите, как проходит запрос через каждый фильтр и где происходит отказ.
👉@BookJava
SecurityContext
не “переходит” автоматически в новые потоки. Для этого используют SecurityContextRepository
и специальные методы в WebFlux.⚠️ Важно: не храните
SecurityContext
в сессии, если у вас stateless-приложение (REST API). Вместо сессии используйте JWT или OAuth 2.0.🧠 5. Авторизация: FilterSecurityInterceptor & AccessDecisionManager
FilterSecurityInterceptor
запускается в конце цепочки фильтров и проверяет доступ к URL. Он запрашивает у SecurityMetadataSource
список необходимых ролей для данного эндпоинта (Spring на основании @PreAuthorize
, HttpSecurity
конфигурации или XML). Затем передаёт дело в AccessDecisionManager
(по умолчанию AffirmativeBased), который опрашивает список AccessDecisionVoter
(например, RoleVoter
для проверок ролей, WebExpressionVoter
для SpEL).
FilterSecurityInterceptor
└─> SecurityMetadataSource (что нужно: ROLE_ADMIN)
└─> AccessDecisionManager.vote()
├─ RoleVoter.vote() → совпадает?
└─ WebExpressionVoter.vote() → SpEL-выражения?
Если хотя бы один голос “grant”,
AffirmativeBased
отпускает запрос (по умолчанию). Можно менять стратегию на Consensus
или Unanimous
.💡 Трюк: чтобы локально протестировать SecurityContext, можно в тестах использовать аннотацию
@WithMockUser(roles = "ADMIN")
и проверять, что нужный эндпоинт доступен.🧠 6. Аннотации & Method Security
Помимо URL-уровня, есть методная проверка:
@EnableMethodSecurity // (Spring Boot 3+) вместо @EnableGlobalMethodSecurity
public class SecurityConfig { ... }
// Где-то в сервисе:
@PreAuthorize("hasRole('ADMIN') and #id == principal.id")
public void deleteUser(Long id) { ... }
* 📌
@PreAuthorize
/ @PostAuthorize
/ @Secured
/ @RolesAllowed
— все используют тот же механизм Voter’ов, но проверяют уже на методах сервиса.* 💡 Совет: включайте методную безопасность только там, где действительно нужна тонкая грануляция.
🧠 7. Хранение паролей & PasswordEncoder
С Java 17+ используйте
PasswordEncoder
с алгоритмами Argon2 или BCrypt:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
⚠️ Никогда не храните пароли в открытом виде и не используйте MD5/SHA-1 — они считаются небезопасными.
🧠 8. Stateless vs Stateful
* Stateful (Сессии): Spring создаёт HTTP-сессию, а
SecurityContextPersistenceFilter
хранит контекст в сессии. Удобно для монолитов с классическим web-приложением.* Stateless (JWT/OAuth2): убираем
SessionCreationPolicy.STATELESS
, используем BearerTokenAuthenticationFilter
, аутентификация и авторизация проверяются по JWT в каждом запросе.💡 Современный стек (Spring Boot 3+):
1. Настраиваем
SecurityFilterChain
с oauth2ResourceServer().jwt()
.2. Подключаем
spring-boot-starter-oauth2-resource-server
.3. Указываем
issuer-uri
или jwk-set-uri
в application.yml
.
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://keycloak.example.com/realms/myrealm
🧠 9. Подпись запросов & CSRF
* По умолчанию CSRF включён для “форменных” запросов (
POST
, PUT
, DELETE
). Для stateless-API его обычно отключают:
http.csrf().disable();
* Если используете формы, не забудьте добавить в шаблон:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
⚠️ Внимание: не отключайте CSRF, если ваше приложение использует сессии и cookie на фронтенде!
💡 Совет по отладке: включите логирование фильтров:
logging.level.org.springframework.security=DEBUG
Тогда в логах вы увидите, как проходит запрос через каждый фильтр и где происходит отказ.
👉@BookJava
👍8❤3
Релиз через два дня. Код готов. Почти...
Остались тесты. Ну, точнее — покрытие. Потому что QA уже дышит в затылок, а ты сидишь и выбираешь: спать или корпеть до утра.
Explyt Test умеет создавать тесты под твой код — сам. Быстро. В IDE. Без плясок.
Хочешь, чтобы релиз прошёл, а не пролетел? Попробуй бесплатно! 👉 explyt.ai
Остались тесты. Ну, точнее — покрытие. Потому что QA уже дышит в затылок, а ты сидишь и выбираешь: спать или корпеть до утра.
Explyt Test умеет создавать тесты под твой код — сам. Быстро. В IDE. Без плясок.
Хочешь, чтобы релиз прошёл, а не пролетел? Попробуй бесплатно! 👉 explyt.ai
😁2👍1
🧠 Конфигурация Spring Boot 3 через
Вместо традиционных
📌 Почему это полезно?
🔴 Полная иммутабельность: поля конфигов больше нельзя случайно перезаписать.
🔴 Минимум «шаблонного» кода: не нужны геттеры, сеттеры,
🔴 Чёткая связь с Java 17+ и актуальными best practices.
💡 Как сделать:
1. Подключаем зависимость:
Это нужно, чтобы IDE и Spring метаинфу подхватили.
2. Создаём
3. Регистрируем бин в Spring:
4. Конфигурируем в
⚠️ Обратите внимание:
🔴 Без
🔴 Уберите все сеттеры и по умолчанию конструктор генерируется автоматически.
🔴 Если вам нужна валидация свойств, добавьте
🧠 Что получилось?
🔴 Минимум «мусора» в коде: один блок
🔴 Полная типобезопасность и поддержка автокомплита при обращении к полям.
🔴 Быстрый переход на Java 17+ подходы без потери функциональности.
💡 Дополнительный лайфхак:
Если вам нужно разделить конфиги по окружениям (dev/prod), просто создайте два
👉@BookJava
record
и @ConstructorBinding
Вместо традиционных
@Data
+ пустого конструктора можно сразу использовать Java 17 record
для настройки свойств:📌 Почему это полезно?
toString()
, equals()
и т.д.💡 Как сделать:
1. Подключаем зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Это нужно, чтобы IDE и Spring метаинфу подхватили.
2. Создаём
record
с аннотацией:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
@ConstructorBinding
@ConfigurationProperties(prefix = "app.mail")
public record MailProperties(
String host,
int port,
String username,
String password
) {}
3. Регистрируем бин в Spring:
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MailProperties.class)
public class AppConfig { }
4. Конфигурируем в
application.yml
(или .properties
):
app:
mail:
host: smtp.example.com
port: 587
username: user@example.com
password: secret123
⚠️ Обратите внимание:
@ConstructorBinding
Spring не сможет смотать значения в record
’ы.@Validated
и JSR-303 аннотации (@NotNull
, @Min
и т.д.).🧠 Что получилось?
record
заменил класс с 4 полями, геттерами и конструктором.💡 Дополнительный лайфхак:
Если вам нужно разделить конфиги по окружениям (dev/prod), просто создайте два
record’а с разными префиксами или используйте @Profile
. В Spring Boot 3 этот подход «из коробки» работает наилучшим образом.👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍2
4 июня(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqvL6bDw
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱2