Java Portal | Программирование
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика Связь: @devmangx РКН: https://clck.ru/3H4WUg
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Java Portal | Программирование
تُعد قناة Java Portal | Программирование (@java_iibrary) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 12 127 مشتركاً، محتلاً المرتبة 10 404 في فئة التكنولوجيات والتطبيقات والمرتبة 54 512 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 12 127 مشتركاً.
بحسب آخر البيانات بتاريخ 07 يونيو, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -138، وفي آخر 24 ساعة بمقدار 2، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 11.37%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 6.26% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 1 379 مشاهدة. وخلال اليوم الأول يجمع عادةً 760 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 4.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل boot, string, void, архитектура, resttemplate.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика
Связь: @devmangx
РКН: https://clck.ru/3H4WUg”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 08 يونيو, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
🎙 Серия 1. Функциональные и нефункциональные требования. Как сбор требований помогает создавать надёжные и масштабируемые решения 🎙 Серия 2. Надёжный API. Принципы проектирования API, которые помогут сделать его консистентным, предсказуемым и поддерживаемым 🎙 Серия 3. Крупноблочная архитектура: карта вашей системы. Как выглядит модель на примере Яндекс Календаря и как ребята применяют её для эффективной коммуникации с различными командами разработки 🎙Серия 4. Практика: Рост баз данных: от единиц запросов к тысячам. Как правильно организовать работу с БД, чтобы система оставалась стабильной и эффективной 🎙 Серия 5. Практика. Взаимодействие со смежными системами. Типичные сложности, с которыми сталкиваются команды при интеграции с внешними сервисами, и как их предотвратить или минимизироватьСмотрите проект, чтобы узнать, как создаются одни из крупнейших облачных сервисов в России: ⭐️ Наш сайт ⭐️ VK Видео ⭐️ Ютуб
@Transactional.
Этот метод не только сохраняет сущность, но и отправляет два письма: одно администратору, другое — пользователю, который сделал запрос.
Класс, отвечающий за отправку почты, помечен аннотацией @Async, но Spring всё равно выполняет его синхронно.
В итоге API обрабатывает запрос целых 12 секунд — очевидно, это неприемлемо.
Вопрос: почему так происходит и как это исправить?
Реальная причина:
Когда используется @Transactional, Spring создаёт прокси для транзакции.
Если внутри этого же контекста вызывается @Async-метод, то Spring не создаёт новый поток — потому что вызов происходит внутри того же прокси.
Иными словами, асинхронный код оказывается «заперт» внутри транзакции.
В результате, коммит в базу ждёт, пока оба письма не будут отправлены.
Как исправить:
Заменить прямой вызов отправки писем на event-publisher подход.
После сохранения запроса просто опубликовать событие, например DemoRequestCreatedEvent.
Асинхронные слушатели (@EventListener + @Async) будут обрабатывать отправку писем вне основной транзакции.
Что получаем:
Транзакция завершается за ~100 мс вместо 12 секунд.
API реагирует почти мгновенно.
Письма всё так же надёжно уходят в фоне.
Использование событий и асинхронных слушателей — не просто красивая архитектурная штука, а реальный способ сделать систему быстрой, масштабируемой и профессиональной.
Дополнительный вопрос:
Кроме событий, какие подходы ты используешь, чтобы отделить транзакционную логику (например, коммит в БД) от побочных эффектов вроде отправки писем или уведомлений?
@Java_IibraryString s1 = "Java";
String s2 = "Java";
System.out.println(s1 == s2); // true
s1 и s2 указывают на один и тот же объект в String Pool → дубликаты не создаются.
Но если сделать так:
String s3 = new String("Java");
System.out.println(s1 == s3); // false
new String() обходит пул и создаёт новый объект в heap.
Зачем это нужно:
→ Экономит память за счёт переиспользования неизменяемых строк.
→ Повышает производительность при повторных строковых значениях.
→ Безопасно для потоков, потому что строки immutable.
Как заставить строку из heap использовать пул?
Ответ:
s3 = s3.intern();
Метод intern() → добавляет строку в пул и возвращает ссылку на объект из пула.
👉 Java Portal@Repository, а где — с аннотацией @Service? Приведи конкретный пример, какую роль каждая из этих аннотаций играет в процессе оформления заказа пользователем.
→
@Component — универсальный бин,
@Service — бизнес-логика,
@Repository — DAO + перевод исключений в DataAccessException,
@Controller — контроллер уровня MVC.
🔸Циклические зависимости
Сценарий: Коллега добавил новую фичу, и теперь твое Spring-приложение не стартует, выдавая BeanCurrentlyInCreationException из-за циклической зависимости между ServiceA и ServiceB.
Предположим, что быстро переработать бизнес-логику невозможно. Какое минимальное изменение кода ты бы предложил, чтобы приложение хотя бы запустилось, и почему это считается временным решением?
→
Spring по умолчанию может использовать проксирование и конструкторную/сеттерную инъекцию.
Лучшее решение — перепроектировать зависимости или использовать @Lazy.
🔸Распространение транзакций
Сценарий: У тебя есть OrderService с методом createOrder(), помеченным @Transactional.
Внутри он вызывает updateInventory() (тоже в OrderService и тоже с @Transactional).
Если updateInventory() выбрасывает runtime-исключение, что произойдет с транзакцией, начатой в createOrder()?
Как изменить дизайн, если нужно, чтобы оба метода выполнялись в отдельных, независимых транзакциях?
→
Транзакция не будет распространяться (прокси не сработает при внутреннем вызове).
Решение — self-injection (внедрение самого себя как зависимости) или использование AOP.
🔸Скоупы бинов
Сценарий: Нужно хранить товары пользователя в корзине и управлять временным списком поисковых фильтров, который очищается после каждого HTTP-запроса.
Какой скоуп ты выберешь для ShoppingCart и какой — для SearchFilter, и почему?
→
@SessionScope — для корзины (привязано к пользовательской сессии),
@RequestScope — для поискового фильтра (новый бин на каждый HTTP-запрос).
🔸Controller Advice
Сценарий: В приложении есть и традиционные веб-эндпоинты с Thymeleaf, и REST API.
Нужно централизовать обработку ошибок (например, перехват ResourceNotFoundException):
Как вернуть страницу 404 для обычных web-эндпоинтов?
Как вернуть JSON с ошибкой 404 для REST API?
→
@ControllerAdvice — используется с @Controller, возвращает view.
@RestControllerAdvice — сочетает @ControllerAdvice + @ResponseBody (для REST API).
🔸Автоконфигурация
Сценарий: Ты добавил в проект стороннюю библиотеку (например, кастомный логгер) и просто положил её JAR в classpath.
Без написания конфигурационных классов Spring автоматически подхватывает нужные бины.
Объясни, как Spring Boot определяет и подключает их при старте.
→
Использует SpringFactoriesLoader, который читает META-INF/spring.factories и конфигурирует бины в зависимости от содержимого classpath.
🔸Ограничение частоты запросов
Сценарий: Твой публичный API перегружен — один клиент шлет слишком много запросов, мешая остальным.
Какой практичный, независимый от технологий подход можно применить для ограничения, например, 100 запросов в минуту на клиента, и где обычно реализуется такая логика?
→
Bucket4j / Resilience4j, счетчики в Redis, лимитирование на уровне API Gateway.
🔸Распределённые транзакции
Сценарий: В микросервисной архитектуре оформление заказа включает два шага — списание товара в Inventory Service и списание денег через Payment Service.
Если списание товара прошло успешно, а оплата — нет, какой шаблон проектирования поможет откатить изменения в Inventory и обеспечить согласованность данных?
→
Шаблон Saga (хореография или оркестрация), либо двухфазный коммит (2PC, но редко используется на практике).
👉 Java Portal@GetMapping, @PostMapping, @PutMapping, @DeleteMapping
- Path variables и request parameters
- Настройка баз данных (H2, MySQL, PostgreSQL)
- Использование JpaRepository и CrudRepository
- Spring Boot DevTools и hot reloading
- Spring Batch, Scheduling и Cron выражения
PHASE 2
- @ControllerAdvice и @ExceptionHandler
- Кастомные ошибки и глобальная обработка исключений
- Базовая аутентификация и настройка безопасности API
- JWT для stateless аутентификации
- HATEOAS и версионирование REST API (URI, параметры, headers)
- Unit-тесты с JUnit и Mockito
- Интеграционные тесты с Spring Boot Test и MockMvc
- Actuator endpoints и кастомные health indicators
PHASE 3
- @Profile и настройка бинов для разных окружений
- Spring Cloud: Eureka Server, Service Discovery, API Gateway
- Spring Cloud Config Server для централизованного управления конфигурациями
- Настройка Spring Boot приложений для работы с Config Server
Чтобы полностью усвоить материал, постройте свои проекты на каждом этапе. Практика поможет закрепить знания и сделает их долговечными.
👉 Java Portal1. Круговой Алгоритм Клиентские запросы отправляются в различные экземпляры сервисов в последовательном порядке. Сервисы обычно должны быть без сохранения состояния. Недостаток: - Эта простейшая версия алгоритма будет эффективно работать только в сферической среде в вакууме, где все серверы обладают почти одинаковой конфигурацией, а все входящие запросы (задачи, процессы) имеют одинаковые приоритет и продолжительность. 2. Закреплённый Круговой Алгоритм Усовершенствование кругового алгоритма. Если первый запрос Алисы отправляется в сервис A, следующие запросы также отправляются в сервис A. 3. Взвешенный Круговой Алгоритм Администратор может указать вес для каждого сервиса. Сервисы с более высоким весом обрабатывают больше запросов, чем другие. 4. Хэш IP/URL Применяет хеш-функцию к IP или URL входящих запросов. Запросы направляются в соответствующие экземпляры на основе результата хеш-функции. Преимущества: - Постоянство сессии – алгоритм гарантирует, что запросы от одного клиента всегда попадают на один и тот же сервер. - Облегчает кеширование данных на стороне сервера для конкретных клиентов. Недостатки: - Если много пользователей приходят из одного диапазона IP, один сервер может быть перегружен. - Неэффективен в средах, где IP клиентов часто меняются (мобильные сети). - Может привести к неравномерной нагрузке, если некоторые клиенты генерируют больше трафика.Динамические алгоритмы
5. Наименьшее Количество Соединений Новый запрос отправляется в экземпляр сервиса с наименьшим количеством одновременных подключений. Преимущества: - Более мощные серверы естественным образом будут обрабатывать больше запросов и, следовательно, иметь больше соединений. И напротив, менее мощные серверы будут получать меньше запросов, что предотвращает их перегрузку. - Гибкость – если один сервер начинает работать медленнее, он будет получать меньше новых запросов. Недостатки: - Алгоритм считает все соединения одинаковыми, не учитывая, что некоторые запросы могут быть более ресурсоёмкими. - Вновь добавленный сервер может получить слишком много запросов, т.к. изначально у него 0 соединений. 6. Наименьшее Время Ответа Новый запрос отправляется в экземпляр сервиса с самым быстрым временем ответа. Аналогичный алгоритм - Наименьший объем трафика Преимущества: - Учёт текущей производительности серверов и динамическая адаптация обеспечивают оптимальный баланс и наилучший пользовательский опыт. - Хорошо работает с серверами разной мощности и приложениями с разными характеристиками. Недостаток: - Сложность реализации – требует постоянного мониторинга и анализа производительности серверов, отсюда повышенная нагрузка на балансировщик.👉 Java Portal
@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();
Плюсы: один эффективный запрос.
Важно: при джойне нескольких коллекций можно получить декартово произведение.
2. Batch Fetching
(@BatchSize или hibernate.default_batch_fetch_size)
Вместо одного запроса на каждого родителя, связанные коллекции загружаются пакетами — по нескольким ID за один запрос.
Пример:
@BatchSize(size = 10)
@OneToMany(...)
private List<Book> books;
Плюсы: уменьшает количество запросов с 1 + N до 1 + (N / batch_size), избегая проблемы декартовых произведений.
3. Entity Graphs
(@EntityGraph — Spring Data JPA / JPA 2.1+)
Позволяет декларативно определить, какие связи нужно подгружать eagerly для конкретного метода репозитория.
Пример:
@EntityGraph(attributePaths = "books")
List<Author> findAll();
Плюсы: гибкая и переиспользуемая стратегия загрузки без явных JPQL JOIN’ов.
Всегда используйте явные стратегии загрузки (такие как JOIN FETCH, @BatchSize или @EntityGraph), чтобы избежать проблемы N+1 и обеспечить эффективное взаимодействие с базой данных.
👉 Java Portal
@Test
void findAll() {
// given
// Все компактно, содержит только необходимую информацию для программиста
User user1 = userDao.save(getUser("test1@gmail.com"));
User user2 = userDao.save(getUser("test2@gmail.com"));
User user3 = userDao.save(getUser("test3@gmail.com"));
// when
List<User> actualResult = userDao.findAll();
// then
// Легко получить доступ к id объектов, т.к. накатывание данных было в самом тесте
assertThat(actualResult).hasSize(3);
List<Integer> userIds = actualResult.stream()
.map(User::getId)
.toList();
assertThat(userIds).contains(user1.getId(), user2.getId(), user3.getId());
}
А чтобы не испортить состояние базы во время проверки, то:
- открываем транзакцию ПЕРЕД выполнением теста (@BeforeEach)
- накатываем данные, вызываем API и проверяем результат (@Test)
- откатываем транзакцию в конце (@AfterEach)
👉 Java Portal@ResponseStatus: простой статический вариант
- Можно навесить на исключение или метод контроллера.
- Всегда возвращает один и тот же HTTP-статус.
- Подход "fire-and-forget": быстро и лаконично в случаях, когда ответ всегда одинаковый.
- Лучше всего подходит для простой обработки ошибок. Например, ResourceNotFoundException, аннотированный @ResponseStatus(HttpStatus.NOT_FOUND), всегда будет возвращать 404.
- Нельзя добавить кастомные заголовки или динамическое тело ответа.
→ ResponseEntity: кастомный инструмент
- Даёт полный программный контроль над формированием HTTP-ответа во время выполнения.
- Можно выставить статус, добавить заголовки и собрать тело ответа так, как требуется по логике.
- Лучше всего подходит для сложных ответов. Например, когда нужно добавить заголовок Location после создания ресурса (201 Created) или вернуть детализированный JSON-объект с информацией об ошибке.
- Это основной инструмент, когда ответ должен зависеть от ситуации.
Комбинация подходов:
Используя @RestControllerAdvice для глобальной обработки исключений, можно применять @ResponseStatus для типовых ошибок, а ResponseEntity — для более специфичных и динамичных ответов. Такой подход даёт одновременно и эффективность, и гибкость.
👉 Java Portal
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
