bookjava | Unsorted

Telegram-канал bookjava - Библиотека Java разработчика

10986

📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

Subscribe to a channel

Библиотека Java разработчика

В асинхронных или веб-сервисах на реактиве нужно быть осторожным: 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

Читать полностью…

Библиотека Java разработчика

«Я слышу свой код»: как работает Java-программист, потерявший зрение

Константин Евтеев собирает Java-код с помощью диктора NVDA, редактирует его в Блокноте и передает на Linux по SSH через самописные bash-скрипты. После потери зрения он не потерял интереса к жизни и желания быть полезным и выстроил собственную инженерную экосистему: оглавления по строкам .txt-файлами, навигация по main и маленьким методам, отладка на слух.

https://habr.com/ru/companies/axiomjdk/articles/913748/

👉@BookJava

Читать полностью…

Библиотека Java разработчика

🚀 Подборка Telegram каналов для программистов

Системное администрирование, DevOps 📌

/channel/bash_srv Bash Советы
/channel/win_sysadmin Системный Администратор Windows
/channel/sysadmin_girl Девочка Сисадмин
/channel/srv_admin_linux Админские угодья
/channel/linux_srv Типичный Сисадмин
/channel/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
/channel/linux_odmin Linux: Системный администратор
/channel/devops_star DevOps Star (Звезда Девопса)
/channel/i_linux Системный администратор
/channel/linuxchmod Linux
/channel/sys_adminos Системный Администратор
/channel/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
/channel/sysadminof Книги для админов, полезные материалы
/channel/i_odmin Все для системного администратора
/channel/i_odmin_book Библиотека Системного Администратора
/channel/i_odmin_chat Чат системных администраторов
/channel/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
/channel/sysadminoff Новости Линукс Linux

1C разработка 📌
/channel/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
/channel/DevLab1C 1С:Предприятие 8
/channel/razrab_1C 1C Разработчик
/channel/buh1C_prog 1C Программист | Бухгалтерия и Учёт
/channel/rabota1C_rus Вакансии для программистов 1С

Программирование C++📌
/channel/cpp_lib Библиотека C/C++ разработчика
/channel/cpp_knigi Книги для программистов C/C++
/channel/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
/channel/pythonofff Python академия.
/channel/BookPython Библиотека Python разработчика
/channel/python_real Python подборки на русском и английском
/channel/python_360 Книги по Python

Java разработка 📌
/channel/BookJava Библиотека Java разработчика
/channel/java_360 Книги по Java Rus
/channel/java_geek Учим Java на примерах

GitHub Сообщество 📌
/channel/Githublib Интересное из GitHub

Базы данных (Data Base) 📌
/channel/database_info Все про базы данных

Мобильная разработка: iOS, Android 📌
/channel/developer_mobila Мобильная разработка
/channel/kotlin_lib Подборки полезного материала по Kotlin

Фронтенд разработка 📌
/channel/frontend_1 Подборки для frontend разработчиков
/channel/frontend_sovet Frontend советы, примеры и практика!
/channel/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
/channel/game_devv Все о разработке игр

Библиотеки 📌
/channel/book_for_dev Книги для программистов Rus
/channel/programmist_of Книги по программированию
/channel/proglb Библиотека программиста
/channel/bfbook Книги для программистов

БигДата, машинное обучение 📌
/channel/bigdata_1 Big Data, Machine Learning

Программирование 📌
/channel/bookflow Лекции, видеоуроки, доклады с IT конференций
/channel/rust_lib Полезный контент по программированию на Rust
/channel/golang_lib Библиотека Go (Golang) разработчика
/channel/itmozg Программисты, дизайнеры, новости из мира IT
/channel/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
/channel/nodejs_lib Подборки по Node js и все что с ним связано
/channel/ruby_lib Библиотека Ruby программиста
/channel/lifeproger Жизнь программиста. Авторский канал.

QA, тестирование 📌
/channel/testlab_qa Библиотека тестировщика

Шутки программистов 📌
/channel/itumor Шутки программистов

Защита, взлом, безопасность 📌
/channel/thehaking Канал о кибербезопасности
/channel/xakep_2 Хакер Free

Книги, статьи для дизайнеров 📌
/channel/ux_web Статьи, книги для дизайнеров

Математика 📌
/channel/Pomatematike Канал по математике
/channel/phis_mat Обучающие видео, книги по Физике и Математике
/channel/matgeoru Математика | Геометрия | Логика

Excel лайфхак📌
/channel/Excel_lifehack

/channel/mir_teh Мир технологий (Technology World)

Вакансии 📌
/channel/sysadmin_rabota Системный Администратор
/channel/progjob Вакансии в IT

Читать полностью…

Библиотека Java разработчика

🗑 Понимание различных сборщиков мусора в Java

🔵 Serial Garbage Collector: Лучший вариант для однопоточных приложений с небольшими кучами. Он использует один поток для выполнения как малых, так и больших сборок мусора, что приводит к значительным паузам, но минимальной нагрузке на систему.

🔵 Parallel Garbage Collector: Подходит для приложений с высокими требованиями к пропускной способности. Использует несколько потоков для выполнения как малых, так и больших сборок мусора, уменьшая время пауз, но при этом увеличивая использование CPU.

🔵 Concurrent Mark-Sweep (CMS) Garbage Collector: Разработан для минимизации пауз за счёт выполнения основной части работы по сборке мусора параллельно с выполнением приложений. Подходит для приложений, где критически важна низкая задержка.

🔵 G1 Garbage Collector: Сбалансированный сборщик мусора, который стремится обеспечить предсказуемое время пауз, разделяя кучу на регионы и выполняя сборку мусора поэтапно. Является хорошим выбором по умолчанию для большинства приложений.

🔵 Z Garbage Collector и Shenandoah: Сборщики мусора с ультранизкой задержкой, разработанные для работы с большими кучами. Основная часть работы по сборке мусора выполняется параллельно, что позволяет минимизировать время пауз даже при очень больших кучах.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

👩‍💻 Хотите выйти за пределы стандартных подходов в Java-разработке? Разобраться в JVM, многопоточности и современных фреймворках?

🔥 Актуальное обучение, курс «Java Developer. Professional» — это 96 часов практики, детальный разбор технологий, код-ревью от опытных экспертов и работа с Spring WebFlux, Kafka, Kubernetes.

После обучения вы сможете разрабатывать сложные Java-приложения уровня Middle+, понимать работу JVM изнутри и писать чистый, оптимизированный код.

🎁 Дарим промокод, который дает скидку на обучение - JAVA_06

➡️ Пройдите вступительное тестирование и получите скидку: https://vk.cc/cMonpN

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

🧠 Сегодня разберём Saga — паттерн, который часто всплывает на собеседованиях уровня сеньор, особенно если речь о микросервисах.

📌 Зачем нужна 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

Читать полностью…

Библиотека Java разработчика

🧠 Как быстро написать компаратор в Java и не забыть про null

Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из 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

Читать полностью…

Библиотека Java разработчика

📊 Приглашаем на открытый урок: Создание RLE архиватора на Java

Хотите узнать, как работают алгоритмы сжатия данных?
В нашем вебинаре мы шаг за шагом создадим архиватор на Java, используя алгоритм RLE. Вы разработаете интерфейс программы и поймете, как реализовать самые эффективные методы сжатия.

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

🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».

🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Algo5

👉 Регистрация на вебинар: https://vk.cc/cMl0ID

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

🧠 10 правил безопасного Java-приложения:

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

Читать полностью…

Библиотека Java разработчика

Spring Framework в деталях

SimpleJdbcInsert - Spring Framework JDBC
АОП в Spring Framework
XML-конфигурация АОП в Spring Framework
Транзакции - Spring Framework в деталях

источник

👉@BookJava

Читать полностью…

Библиотека Java разработчика

🔐 Основы сжатия данных: создаем RLE архиватор

Приглашаем на открытый урок.

🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».

На этом вебинаре мы начнем создавать собственный архиватор на Java. Разработаем базовую структуру программы с пользовательским интерфейсом и реализуем алгоритм RLE (кодирование длин серий) для сжатия данных. Изучим как базовую, так и улучшенную версию RLE.

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

Практическое погружение в мир алгоритмов сжатия данных для всех, кто интересуется программированием и структурами данных.

🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Algo5

👉 Регистрация на вебинар: https://vk.cc/cMenHb

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

💻 Модели межсервисного взаимодействия

Изучите различные модели взаимодействия между микросервисами и выберите оптимальный подход для вашего проекта

Приглашаем на открытый урок.

🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Software Architect».

На вебинаре вы узнаете:

✔️ Основные принципы и типы межсервисного взаимодействия.
✔️ Синхронные и асинхронные модели взаимодействия: плюсы и минусы.
✔️ Использование API Gateway и Service Mesh для управления трафиком.
✔️ Паттерны и лучшие практики для надежного и масштабируемого взаимодействия.
✔️ Примеры успешных реализаций межсервисного взаимодействия в реальных проектах.

Вебинар будет полезен:
- Разработчикам, работающим с микросервисной архитектурой.
- Архитекторам ПО, стремящимся оптимизировать межсервисное взаимодействие.
- Backend и Fullstack разработчикам, заинтересованным в улучшении взаимодействия между сервисами.
- DevOps-инженерам, отвечающим за развертывание и управление микросервисами.

🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - SoftwareArc_06

👉 Регистрация на вебинар: https://vk.cc/cMcrjZ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

🧠 Dependency Inversion Principle (D в SOLID)
Зависимости должны идти от высокоуровневой политики к низкоуровневым деталям, а не наоборот. Абстракции — хозяева, реализации — обслуживающий персонал.


📌 Коротко о сути

* Модули верхнего уровня (бизнес-логика) зависят только от интерфейсов/абстракций.
* Модули нижнего уровня (база, сеть, файлы) также зависят от тех же абстракций.
* Сами абстракции не знают ничего о деталях, тем самым разрывая «бетонную» сцепку между слоями.


💡 Мини-пример (Java 17+, Spring Boot 3+)


// 1️⃣ Абстракция — контракт
public interface NotificationSender {
void send(Message msg);
}

// 2️⃣ Верхний уровень — бизнес-служба
@Service
public class BillingService {
private final NotificationSender sender;

public BillingService(NotificationSender sender) {
this.sender = sender; // зависим от контракта
}

public void bill(Client c) {
// ...
sender.send(new Message("Invoice #42"));
}
}

// 3️⃣ Низкий уровень — деталь
@Component
public class EmailSender implements NotificationSender {
public void send(Message msg) {
// SMTP-магия
}
}


BillingService может жить в модульном jar без spring-email-starter и SMTP-кода — протестировать его теперь элементарно.


⚠️ Где рождаются проблемы

1. Путаница DI container ≠ DIP
IoC/DI-фреймворк (Spring, CDI) — лишь удобный способ «сращивать» зависимости, но принцип работает и без контейнера (чистый constructor injection).

2. Абстракции ради галочки
Интерфейс OneImplService с единственной реализацией ломает читаемость, тесты и автоконфиг 📉.
➜ Создавай абстракцию, когда реально нужны сменяемость, тестируемость или расширяемость.

3. Утечки деталей
Если интерфейс таскает DTO из слоя хранения, ты всё ещё «протёк» к базе. Держи контракты чистыми.

4. Слепая вера в фреймворк
Жизненный цикл бинов, прокси, lazy-init — магия мешает понимать, кто кем владеет.
➜ Всегда можешь собрать объект вручную в юнит-тесте. Если сложно — запах нарушения DIP.

5. Слишком много уровней абстракций
«Контроллер → сервис → менеджер → порт → адаптер → репозиторий» превращает код в матрёшку. Дизайн важнее количества слоёв.


📝 Практические советы

* Используй constructor injection по умолчанию. Поле final = явная зависимость.
* Группируй интерфейсы по use-case, а не по технологии (например, TransferPort, а не JdbcTransferRepository).
* В тестах не мокай фреймворк — мокай контракт.
* Для одноразовых реализаций начни с class. Если появится второй вариант — быстро вынесешь интерфейс (IDE поможет).
* Проверка себя: можно ли запустить модуль верхнего уровня без нижнего? Если да — DIP соблюдён.


💬 Итог
DIP — это не про «везде интерфейсы» и не про «подключи Spring». Это про правильное направление зависимостей, которое делает код гибким, тестируемым и не заложником технологий. А проблемы возникают, когда путают инструмент с принципом и забывают, что абстракция должна прятать детали, а не выпячивать их.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

Три похожих слова в Java — final, finally, finalize — но смысл у них совершенно разный. Разберёмся 🧠


🔒 final

Ключевое слово. Используется для ограничений:

* final class — нельзя наследовать.
* final method — нельзя переопределить.
* final variable — нельзя изменить значение (один раз присвоил — всё).

📌 Особенно важно для immutability и thread-safety.


final int x = 10;
x = 20; // ошибка компиляции



🧯 finally

Блок в конструкции try-catch-finally. Выполняется всегда, даже если был return или exception.

💡 Используется для освобождения ресурсов: закрытия потоков, соединений и т.д.


try {
// что-то может выбросить исключение
} catch (Exception e) {
// обработка ошибки
} finally {
// всегда выполнится
}



⚰️ finalize()

Метод из Object, вызывался перед удалением объекта сборщиком мусора.

⚠️ УСТАРЕЛ с Java 9, удалён в Java 18. Не используй.

🔪 Непредсказуем, плохо работает, тормозит GC. Вместо него — AutoCloseable и try-with-resources.


@Override
protected void finalize() throws Throwable {
System.out.println("До свидания...");
}



🧠 Важно не путать:

* final — про нельзя менять
* finally — про всегда выполнится
* finalize — про устаревший и бесполезный метод

👉@BookJava

Читать полностью…

Библиотека Java разработчика

👩‍💻 Хотите научиться эффективно работать с многопоточными приложениями на Java?

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

🗓 26 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Professional».

Освоив принципы работы потокобезопасных очередей, вы сможете создать более производительные и стабильные многопоточные приложения. Эти знания откроют новые возможности для вашего профессионального роста в Java-разработке.

🔗 Ссылка на регистрацию: https://vk.cc/cM8APp

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

📌 Spring Security: основная архитектура

🧠 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);

Читать полностью…

Библиотека Java разработчика

🧠 Чем Spring Native Image отличается от обычного Spring-приложения?

📌 Обычный Spring:

* Запускается на JVM, динамически загружает классы, использует рефлексию.
* Медленный старт (секунды), выше потребление памяти.
* Подходит для сложной логики с динамическим поведением (настройки, рефлексия, прокси).

📌 Spring Native Image (GraalVM):

* Компиляция в нативный бинарник.
* ⚡️ Мгновенный старт (миллисекунды), низкое потребление памяти.
* Отсутствие динамики: ограничения в рефлексии, прокси и динамической загрузке.

💡 Когда что использовать?

* Native Image — идеален для микросервисов и Serverless-приложений.
* Обычный JVM Spring — когда важна максимальная гибкость и динамика.

⚠️ Помни, что Native Image требует больше усилий по настройке и ограничений на библиотеки.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

Как не завалить приложение из-за N+1 запросов в Hibernate 🧨

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

Читать полностью…

Библиотека Java разработчика

Серия статей: «Дюк, вынеси мусор!»
Все, что нужно знать о сборке мусора в 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

Читать полностью…

Библиотека Java разработчика

🧠 Сейчас расскажу о распределённых транзакциях в 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:


// НЕ рекомендуется:
@EnableTransactionManagement
public class Config {
@Bean
public JtaTransactionManager transactionManager() {
return new JtaTransactionManager();
}
}

// Лучше outbox + отдельный publisher


🧠 В 99% случаев проще и надёжнее строить архитектуру вокруг событий и простых локальных транзакций, чем бороться с XA.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

Ищем Java-разработчика в команду онлайн-рекомендаций AI VK 🤖

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

Если любите технически сложные задачи и хотите работать с большими данными, ждём ваше резюме на сайте VK Team!

Читать полностью…

Библиотека Java разработчика

Сегодня покажу вам интересный костыль, который до сих пор живёт в JDK и влияет на сортировку списков.

🧠 Если ты когда-нибудь пробовал сортировать 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

Читать полностью…

Библиотека Java разработчика

Двоичная Java: CDS, CRaC и AOT для ускорения запуска и прогрева JVM

В этой статье вы узнаете о повышении перфоманса Java-приложений. Разберём:

🔹Как работает HotSpot.
🔹Процессы исполнения байт-кода и в чём же основные проблемы.
🔹Технологии для повышения перформанса: CDS, CRaC и AOT.
🔹Два мира сборки приложений: статический и динамический.

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

https://habr.com/ru/companies/axiomjdk/articles/911568/

👉@BookJava

Читать полностью…

Библиотека Java разработчика

🔥 Хардкорный тест для разработчиков, тимлидов и архитекторов!

💻 Ответьте на 11 вопросов и узнайте, достаточно ли у вас знаний, чтобы пройти онлайн-курс «Software Architect» в OTUS по спец.цене.

🦾 Курс поможет прокачать весь арсенал навыков, необходимых архитектору ПО.

❇️ Пройти тест - https://vk.cc/cMj0Ns

💣 Знание продвинутых техник построения архитектуры — это топ-компетенции для программистов в 2025 году. За 4 месяца обучения вы изучите тактики работы с атрибутами качества и архитектурные решения, а также узнаете, как проектировать архитектуру мобильных приложений, микросервисов, баз данных и ML архитектуру пайплайнов.

🎁 Для получения спец.цены используйте промокод, который дает скидку на обучение - SoftwareArc_06

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

🧠 Проверяешь аргументы вручную? Используй мощь системы типов Java!

📌 Ситуация: часто в методах видишь явные проверки вроде:


public void process(User user) {
if (user == null || user.getName() == null) {
throw new IllegalArgumentException("User или его имя не могут быть null");
}
// код обработки...
}


⚠️ Это шумно и ненадежно: легко пропустить проверку или некорректно сформулировать сообщение.

💡 Современный подход (Java 17+): явно обозначь контракт метода через типы и аннотации, и пусть JVM делает проверки автоматически!

Используй стандартные средства:


import java.util.Objects;

public void process(User user) {
Objects.requireNonNull(user, "User не должен быть null");
Objects.requireNonNull(user.getName(), "Имя пользователя не должно быть null");
// код обработки...
}


или лаконично через Lombok:


import lombok.NonNull;

public void process(@NonNull User user) {
// Lombok автоматически вставит проверку на null
}


🔸 Преимущества:

* Ясность кода и контракта.
* Меньше boilerplate и человеческого фактора.
* Fail fast: сразу ловим ошибки, не откладывая.

🧠 Запомни: чем строже твоя система типов и контрактов, тем меньше неожиданностей в продакшене.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

📌 Обход коллекций в Java: делаем правильно!

Часто вижу, как разработчики по привычке используют старый подход с циклом for. Сегодня напомню оптимальные способы перебора коллекций в Java.

🧠 1. Foreach (Java 5+)
Коротко, ясно, подходит для большинства задач:


for (String item : collection) {
// обработка элемента
}


🧠 2. Метод forEach (Java 8+)
Отлично подходит для функционального стиля:


collection.forEach(item -> {
// обработка элемента
});


⚠️ Важно: нельзя модифицировать саму коллекцию во время такого обхода!

🧠 3. Stream API (Java 8+)
Идеален для сложной обработки с фильтрацией, маппингом и т.д.:


collection.stream()
.filter(Objects::nonNull)
.map(String::toUpperCase)
.forEach(System.out::println);


💡 Что выбрать?

* Простой перебор? Используй цикл foreach.
* Нужно быстро и функционально? collection.forEach().
* Сложные манипуляции? Только Stream API.

📌 Используйте современные подходы, это читаемость и удобство поддержки вашего кода!

👉@BookJava

Читать полностью…

Библиотека Java разработчика

📌 Stream API: забудьте про peek()

Метод peek() в Java Stream API выглядит удобным для отладки, но его использование в реальном коде часто приводит к проблемам.

⚠️ Почему не стоит полагаться на peek()?

* peek() — промежуточная операция, которая не гарантирует вызов функции для каждого элемента стрима.
* Поведение зависит от терминальной операции: например, при некоторых оптимизациях JDK (особенно в параллельных стримах) вызов peek() может быть пропущен или работать непредсказуемо.

💡 Пример опасного кода:


List<String> names = Stream.of("Java", "Spring", "Hibernate")
.peek(System.out::println) // 👈 анти-паттерн!
.collect(Collectors.toList());


🧠 Лучший подход: используйте peek() исключительно для дебага, но никогда — для изменения состояния или важных операций.

Правильная замена:
Если нужно выполнить действие над каждым элементом, используйте явный и безопасный подход:


List<String> names = Stream.of("Java", "Spring", "Hibernate")
.map(name -> {
log.info("Processing: {}", name); // или другая логика
return name;
})
.collect(Collectors.toList());


Или вообще вынесите логику за пределы стрима.

🧹 Держите код понятным и безопасным — забудьте про peek().

👉@BookJava

Читать полностью…

Библиотека Java разработчика

Ищете эффективные инструменты для создания DSL?

Узнайте, как Kotlin может упростить разработку с помощью JsonBuilder!

Приглашаем на открытый урок.

🗓 22 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».

На открытом уроке вы разберете, как Kotlin позволяет создавать DSL (Domain-Specific Languages), оптимизируя процесс разработки. Мы покажем теорию и практику создания DSL на примере JsonBuilder.

Вы не только научитесь создавать собственные DSL, но и освоите замыкания и extension-методы Kotlin, которые дадут вам дополнительные преимущества при написании чистого и гибкого кода.

🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Kotlin5

👉 Регистрация на вебинар: https://vk.cc/cMaDZP

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Читать полностью…

Библиотека Java разработчика

🧠 Ленивая инициализация через Supplier — элегантная альтернатива double-checked locking

Когда нужно отложить создание тяжёлого объекта до первого обращения, многие вспоминают double-checked locking:


private volatile SomeHeavyObject obj;

public SomeHeavyObject getObj() {
if (obj == null) {
synchronized (this) {
if (obj == null) {
obj = new SomeHeavyObject();
}
}
}
return obj;
}


⚠️ Многословно, хрупко, легко ошибиться. Есть лучше.

📌 Современный подход — использовать Supplier с ленивой инициализацией:


private final Supplier<SomeHeavyObject> lazyObj = Suppliers.memoize(SomeHeavyObject::new);

public SomeHeavyObject getObj() {
return lazyObj.get();
}


💡 Suppliers.memoize — из Guava. Он гарантирует потокобезопасную инициализацию один раз при первом вызове get().

Плюсы:
— Читается за секунду
— Потокобезопасно
— Нет дублирования кода
— Легко тестировать и заменять

🔁 Альтернатива в чистой Java: использовать AtomicReference и updateAndGet, но это уже длиннее и менее выразительно.

Если используешь Spring — можно просто обернуть бин в @Lazy. Но вне Spring, в обычных Java-приложениях или утилитах — Supplier с memoize() идеален.

👉@BookJava

Читать полностью…

Библиотека Java разработчика

Что такое механизм try-with-resources?

Механизм try-with-resources в Java — это конструкция, которая упрощает работу с ресурсами, требующими закрытия (например, файлы, сокеты, соединения с БД и т.д.). Он автоматически закрывает ресурсы после завершения блока try, избавляя от необходимости писать finally вручную.

📌 Поддерживается с Java 7
📌 Ресурсы должны реализовывать интерфейс AutoCloseable

💡 Пример:


try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
// reader будет закрыт автоматически, даже если произойдёт исключение


🧠 Почему это важно:

* Уменьшает boilerplate-код
* Исключает утечки ресурсов
* Упрощает обработку исключений

⚠️ Совет:

С Java 9 можно использовать уже объявленные переменные, если они final или effectively final:


BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
try (reader) {
System.out.println(reader.readLine());
}


👉@BookJava

Читать полностью…
Subscribe to a channel