ch
Feedback
Java Portal | Программирование

Java Portal | Программирование

前往频道在 Telegram

Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика Связь: @devmangx РКН: https://clck.ru/3H4WUg

显示更多

📈 Telegram 频道 Java Portal | Программирование 的分析概览

频道 Java Portal | Программирование (@java_iibrary) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 12 130 名订阅者,在 技术与应用 类别中位列第 10 402,并在 俄罗斯 地区排名第 54 525

📊 受众指标与增长动态

невідомо 创建以来,项目保持高速增长,吸引了 12 130 名订阅者。

根据 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),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。

12 130
订阅者
+224 小时
-287
-13830
帖子存档
Spring Boot: можно добавить глобальные метаданные OpenAPI с помощью аннотации @OpenAPIDefinition. Размести её на главном клас
Spring Boot: можно добавить глобальные метаданные OpenAPI с помощью аннотации @OpenAPIDefinition. Размести её на главном классе приложения Spring Boot или в отдельном конфигурационном классе.
@SpringBootApplication
@OpenAPIDefinition(
    info = @Info(
        title = "Product Management API",
        version = "v1.0",
        description = "Product API Example",
        termsOfService = "https://www.example.com/terms",
        contact = @Contact(
            name = "API Support",
            email = "support@example.com",
            url = "https://example.com/support"
        ),
        license = @License(
            name = "Apache 2.0",
            url = "https://www.apache.org/licenses/LICENSE-2.0"
        )
    )
)
public class ApiApplication {
}

Если у тебя Spring Boot приложение подключено как вложенный модуль и оно использует поддержку Docker Compose, то в IntelliJ IDEA нужно задать MODULE_WORKING_DIRECTORY, чтобы среда смогла корректно определить, где лежит файл compose.yaml. 👉 Java Portal

Spring Boot: для новых приложений выбирайте WebClient вместо RestTemplate ~ Реактивный и неблокирующий ~ Работает на event-lo
Spring Boot: для новых приложений выбирайте WebClient вместо RestTemplate ~ Реактивный и неблокирующий ~ Работает на event-loop, а не на модели один поток на запрос ~ Отлично подходит для микросервисной архитектуры
❌ RestTemplate (blocking)

@Service
public class ItemService {

    private final RestTemplate restTemplate;

    public ItemService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public Item getItem(Long id) {
        return restTemplate.getForObject(
            "https://api.example.com/items/{id}",
            Item.class,
            id
        );
    }
}

✅ WebClient (non-blocking)

@Service
public class ItemService {

    private final WebClient webClient;

    public ItemService(WebClient webClient) {
        this.webClient = webClient;
    }

    public Mono<Item> getItem(Long id) {
        return webClient.get()
            .uri("/items/{id}", id)
            .retrieve()
            .bodyToMono(Item.class);
    }
}
👉 Java Portal

Создаём первый Minecraft мод и подробно разбираем Mixin. Просто и понятно Эта статья была написана из-за отсутствия адекватны
Создаём первый Minecraft мод и подробно разбираем Mixin. Просто и понятно Эта статья была написана из-за отсутствия адекватных русскоязычных руководств по моддингу, особенно для новых версий Minecraft. То, что описано в статье, будет применимо для таких загрузчиков модов, как Fabric и Forge, а также для реализации различных функций. 👉 Java Portal

🔴 Завтра тестовое собеседование с Java-разработчиком 24 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собес
🔴 Завтра тестовое собеседование с Java-разработчиком 24 декабря(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Сергею Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

Java-совет: избегайте глубоко вложенных if/else. Используйте guard clauses (ранние выходы из метода) вместо этого.
❌ Вложенные if-else:

public void processOrder(Order order) {
    if (order != null) {
        if (order.isPaid()) {
            if (order.getItems().size() > 0) {
                // Обработка заказа
                System.out.println("Заказ обработан");
            } else {
                System.out.println("В заказе нет позиций");
            }
        } else {
            System.out.println("Заказ не оплачен");
        }
    } else {
        System.out.println("Заказ равен null");
    }
}

✅ Использование guard clauses (читается проще):

public void processOrder(Order order) {
    if (order == null) {
        System.out.println("Заказ равен null");
        return;
    }

    if (!order.isPaid()) {
        System.out.println("Заказ не оплачен");
        return;
    }

    if (order.getItems().isEmpty()) {
        System.out.println("В заказе нет позиций");
        return;
    }

    // Обработка заказа
    System.out.println("Заказ обработан");
👉 Java Portal

Kubernetes-совет: Java-приложения обычно требуют больше CPU на старте, чем во время обычной работы ☕️ Эта политика Kyverno: a
Kubernetes-совет: Java-приложения обычно требуют больше CPU на старте, чем во время обычной работы ☕️ Эта политика Kyverno:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: resize-pod-policy
spec:
  mutateExistingOnPolicyUpdate: false
  rules:
    - name: resize-pod-policy
      match:
        any:
          - resources:
              kinds:
                - Pod/status
                - Pod
      preconditions:
        all:
          - key: "{{request.object.status.containerStatuses[0].ready}}"
            operator: Equals
            value: true
      mutate:
        targets:
          - apiVersion: v1
            kind: Pod.resize
            name: "{{request.object.metadata.name}}"
        patchStrategicMerge:
          spec:
            containers:
              - (name): sample-app-on-kubernetes
                resources:
                  limits:
                    cpu: 0.5
- отслеживает момент завершения старта pod’а - обновляет ресурсы pod’а прямо на месте - снижает CPU-лимиты после старта Итог: более быстрый запуск и меньшие затраты Вот моя статья об этом 👉 Java Portal

Spring Boot наконец получил нативную поддержку gRPC Забудьте о сторонних стартерах и костылях — Spring gRPC 1.0 GA уже здесь.
Spring Boot наконец получил нативную поддержку gRPC Забудьте о сторонних стартерах и костылях — Spring gRPC 1.0 GA уже здесь. Теперь можно строить высокопроизводительные RPC-сервисы с Protocol Buffers прямо из коробки, без плясок с бубном. 👉 Java Portal

Когда ты уже не джун и даже не мидл, на собеседованиях по Java почти не задают вопросы в стиле «что такое HashMap». В ход иду
Когда ты уже не джун и даже не мидл, на собеседованиях по Java почти не задают вопросы в стиле «что такое HashMap». В ход идут сценарии из реальной жизни. Разберём типичный кейс. Твой сервис — оркестратор. Он дергает несколько downstream-сервисов, чтобы обработать запрос. Один из них проблемный: медленный и периодически отвечает 503 Service Unavailable. 1. Как сделать сервис устойчивым к ненадёжному downstream Первое, что здесь просится » Circuit Breaker. Идея простая: если зависимый сервис начинает фейлиться, мы перестаём его дёргать, чтобы: - не тратить ресурсы, - не увеличивать латентность, - не убивать весь сервис каскадными таймаутами. Реализация с Resilience4j: Подключаем зависимость и оборачиваем вызов проблемного сервиса в CircuitBreaker. Ключевые состояния: Всё нормально. Запросы проходят. Ошибки считаются. Порог ошибок превышен. Все вызовы сразу фейлятся, downstream даже не вызывается. Пробный режим. Ограниченное число запросов, чтобы проверить — ожил сервис или нет. Пример:
@CircuitBreaker(name = "inventoryService", fallbackMethod = "inventoryFallback")
public InventoryResponse getInventory(String productId) {
    return inventoryClient.getInventory(productId);
}
Конфиг обычно задаётся через application.yml: - процент ошибок - sliding window - waitDurationInOpenState - permittedNumberOfCallsInHalfOpenState 2. Что делать, когда circuit открыт (fallback) Тут нет универсального ответа » зависит от бизнеса. Типовые варианты: 🔹Кэш Если данные не критичны к свежести: - Redis - локальный cache - stale-данные лучше, чем 503
private InventoryResponse inventoryFallback(String productId, Throwable ex) {
    return cacheService.getInventory(productId);
}
🔹Дефолтный ответ Если можно вернуть «безопасное» значение: - пустой список - available = false - статус UNKNOWN 🔹Очередь Если запрос важен, но не срочный: - кладём событие в Kafka / Rabbit - обрабатываем асинхронно - отвечаем клиенту 202 Accepted На практике часто комбинируют: кэш + деградация функциональности. 3. Глобальная обработка ошибок через @RestControllerAdvice Чтобы не размазывать try/catch по всему коду, делаем централизованный обработчик. Пример бизнес-исключения
public class ProductNotFoundException extends RuntimeException {
    public ProductNotFoundException(String id) {
        super("Product not found: " + id);
    }
}
Глобальный handler
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ProductNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleProductNotFound(ProductNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            "PRODUCT_NOT_FOUND",
            ex.getMessage()
        );
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
}

JSON-ответ
{
  "code": "PRODUCT_NOT_FOUND",
  "message": "Product not found: 123"
}
Плюсы подхода: - чистые контроллеры - единый формат ошибок - нормальная мапа бизнес-ошибок на HTTP-статусы Итог На таком вопросе проверяют не знание аннотаций, а мышление: - понимаешь ли ты отказоустойчивость - умеешь ли деградировать сервис - разделяешь ли бизнес-ошибки и технические фейлы Это уже разговор не про «Java», а про архитектуру продакшн-сервисов 👉 Java Portal

Java Tip: Начиная с Java 14 можно использовать record для создания компактных неизменяемых объектов, которые просто переносят
Java Tip: Начиная с Java 14 можно использовать record для создания компактных неизменяемых объектов, которые просто переносят данные. » Они короче обычных POJO » У них из коробки есть equals(), hashCode() и toString() » По умолчанию они неизменяемые Классический POJO:
public class Book {
    private final String title;
    private final int price;

    public Book(String title, int price) {
        this.title = title;
        this.price = price;
    }

    // геттеры, toString, equals и hashCode
}
Вместо этого можно создать record:
public record Book(String title, int price) {}
Смысл ровно тот же, но без бойлерплейта. 👉 Java Portal

Когда всё живёт в одной базе данных, с транзакциями всё просто. BEGIN → COMMIT → ROLLBACK. Но в распределённых системах всё резко усложняется. В чём реальная проблема ??? В распределённых системах нельзя сделать одну транзакцию на всё сразу по нескольким причинам: - несколько сервисов - несколько баз данных - множество возможных отказов Классического rollback больше не существует. И тут появляется паттерн Saga. Saga это последовательность локальных транзакций, которые координируются между собой. Каждый шаг: - выполняет своё изменение - фиксируется - и определяет, как себя компенсировать, если дальше что-то пойдёт не так Глобальной транзакции нет. Есть eventual consistency. Простой пример » Создание заказа может включать: 1. Создать заказ 2. Зарезервировать товар 3. Провести оплату Если на шаге 3 происходит сбой, глобального rollback нет. Выполняются компенсирующие действия: - освободить резерв - пометить заказ как отменённый Это и есть Saga. Два способа реализации Saga - Хореография: - сервисы реагируют на события - центрального координатора нет - слабая связность - сложнее проследить общий поток Оркестрация: - есть компонент-координатор - поток шагов явно описан - проще рассуждать о логике - выше связность
Ни один подход не является универсально лучшим. Всё зависит от системы и контекста.
Частая ошибка » Считать, что Saga — это замена ACID-транзакциям. Это не так. Saga меняет сам контракт: - допускаются промежуточные состояния - компенсации проектируются явно - принимается факт, что система может упасть на середине процесса Когда Saga действительно имеет смысл - долгоживущие процессы - несколько сервисов - реальные побочные эффекты: платежи, доставки, резервы - ситуации, где технического rollback не существует Если всё находится в одной базе данных, Saga не нужна. Здесь легко уйти в оверинжиниринг. Ключевая мысль:
Saga не убирает сложность. Она делает её явной.
Явная сложность лучше, чем спрятанная за предположениями, которые больше не работают. В распределённых системах сбои — это не исключение, а часть нормального потока. Паттерн Saga не избавляет от всех проблем, но помогает избежать беспорядка. А в продакшене это уже большая разница. ☃️ 👉 Java Portal

Этот проект показывает систему отслеживания местоположения курьера в реальном времени, похожую на то, как это реализовано в Zomato или Swiggy, и построенную на Spring Boot и Apache Kafka. 👉 Java Portal

Spring Boot 4 теперь полностью безопасен по работе с null — большой плюс для Kotlin-разработчиков. С поддержкой JSpecify в Kotlin 2.2 наконец-то можно избавиться от платформенных типов и получить корректную работу с null даже в обобщённых типах. Подробнее и попробовать Spring с Kotlin ☺️ 👉 Java Portal

Сегодня в рубрике crazy Java: этот код работает (на Java 25):
<T extends Integer> void test(T t) {
    t++;
    // t += 1;
    IO.println(t);
}

void main() {
    test(10);
}
Но если заменить t++ на t += 1, всё ломается. Ошибка:
Main.java:3: error: incompatible types: int cannot be converted to T
👉 Java Portal

В JDK 26 появилась новая фича: HttpClient, который входит в Java SE ещё со времён JDK 11, теперь поддерживает HTTP/3 😱
HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)
    .build(); // создать экземпляр HttpClient с HTTP/3 в качестве предпочтительной версии

URI reqURI = new URI("https://www.google.com/");
HttpRequest req = HttpRequest.newBuilder()
    .uri(reqURI)
    .build(); // создать экземпляр запроса

final HttpResponse.BodyHandler<String> bodyHandler =
    BodyHandlers.ofString(StandardCharsets.UTF_8);

HttpResponse<String> resp = client.send(req, bodyHandler);
// отправить запрос и получить ответ в виде строки

System.out.println(
    "status code: " + resp.statusCode() +
    " HTTP protocol version: " + resp.version()
); // вывести код ответа и используемую версию HTTP
Подробнее 👉 Java Portal

Совет по Spring Boot: используйте TaskScheduler для реализации лёгких динамических задач. Для более сложных сценариев лучше смотреть в сторону Quartz. Инжектим и используем:
@Autowired
TaskScheduler scheduler;

scheduler.schedule(
    () -> System.out.println("Hello!"),
    new CronTrigger("0 */5 * * * *") // каждые 5 минут
);
Инжектируемый бин — это ThreadPoolTaskScheduler, встроенная реализация сразу TaskScheduler и ScheduledExecutorService При необходимости конфигурацию можно кастомизировать:
@Configuration
@EnableScheduling
public class SchedulerConfig {

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5);
        scheduler.setThreadNamePrefix("my-scheduler-");
        scheduler.initialize();
        return scheduler;
    }
}
👉 Java Portal

Случайные UUID убивают производительность базы данных. Ты перешел с целочисленных ID (1, 2, 3…) на UUID (a1b2-3c4d-…) ради безопасности или распределенной генерации. И вдруг записи в БД стали медленнее. Иногда намного. Вот почему. Фрагментация индексов. Большинство индексов в БД это B-Tree (сбалансированные отсортированные деревья). Физическое расположение данных имеет значение. 1. Последовательные ID Когда ты вставляешь последовательные числа (1, 2, 3), новые записи всегда попадают в самый правый лист индекса. Записи предсказуемые и последовательные. Максимальные cache hit’ы. Страницы индекса остаются заполненными на 100%. Это максимальная скорость, на которую способна твоя база. 2. Случайные UUIDv4 UUIDv4 равномерно случайные. Это значит, что каждая новая вставка может попасть в любое место дерева. Из-за этого: -» База постоянно подгружает случайные страницы с диска в память (random I/O). -» Page split. Если целевая страница заполнена, БД вынуждена делить ее пополам, в итоге получаются две полупустые страницы. -» Эффект швейцарского сыра. Индекс раздувается и заполняется дырками, зря тратя RAM и место на диске. -» Когда размер индекса превышает объем доступной памяти, пропускная способность на запись может просесть на 20–90%. 3. UUIDv7 Перестань использовать UUIDv4 в качестве primary key. Используй UUIDv7 (стандартизирован в RFC 9562). UUIDv7 содержит таймстемп в начале ID, поэтому он сортируемый. В итоге ты получаешь лучшее из двух миров: -» Распределенная генерация, без центрального счетчика. -» Монотонные вставки. В B-Tree они ведут себя почти как последовательные числа, без фрагментации. -» Безопасность. Нельзя просто угадать ID (атакующий не узнает, что пользователь 101 идет сразу после 100), хотя стоит учитывать, что время создания записи становится видно. Итог простой: ты сохраняешь удобство UUID и избавляешься от перфоманс-потерь. 👉 Java Portal

Реальная история: Дизайнерское агентство разработало интерфейс приложения в сервисе Figma, но из-за того, что карты Visa и Ma
Реальная история: Дизайнерское агентство разработало интерфейс приложения в сервисе Figma, но из-за того, что карты Visa и Mastercard оказались заблокированы, не смогли выгрузить проект. Осложнялось всё тем, что они могли олатить сервис только с корпоративной карты. Читпей организовали оплату в течение 10 минут. Ребята оплатили подписку, и выгрузили проект. Интерфейс приложения был спасён! Что делает CheatPay: 🔘Помогает оплатить зарубежные сервисы российскими картами, в том числе Visa и Mastercard. 🔘Восстанавливают доступ к аккаунту 🔘Работают прозрачно с оплатой на ИП и всеми закрывающими документами Например: Потеряли доступ к Zoom, Airtable, Atlassian, Canva и другим программам для управления IT-проектами? Простаивают проекты в Adobe Photoshop, Premiere Pro и After Effects? Другие сервисы? Помогут. Обращаться в https://t.me/cheatpay_ru

Тема Islands теперь используется по умолчанию во всех IDE от JetBrains. Более мягкий и сбалансированный внешний вид, рассчитанный на комфорт и концентрацию во время работы. Посмотреть подробнее 👉 https://jb.gg/discover-the-islands 👉 Java Portal

WebFlux часто вызывает путаницу, потому что его обычно объясняют со стороны инструмента, а не со стороны проблемы. Поэтому начнем с базы. Сначала: блокирующий vs неблокирующий код -» Блокирующий код: Поток встает и ждет, пока операция не завершится. Пока ждет, он ничего больше делать не может. -» Неблокирующий код: Поток делегирует ожидание и остается свободным для других задач. Когда результат готов, выполняется продолжение. Это не быстрее. Это просто более эффективное использование потоков. Еще одно ключевое понятие перед тем как идти дальше: Backpressure. Это способность системы регулировать поток данных, чтобы не перегружать потребителя. Представь так: потребитель может сказать продюсеру: «присылай только столько, сколько я успеваю обработать». Теперь к WebFlux. WebFlux позволяет строить полностью неблокирующие приложения end-to-end: -»Неблокирующий сервер (Netty) -»Неблокирующие API -»Проброс backpressure без перегрузки потребителя -»Реактивная модель (Mono, Flux) Ключевое слово здесь end-to-end. Если хотя бы одна часть блокирует, весь выигрыш размывается. Самая частая ошибка при работе с WebFlux Использовать WebFlux, а потом: -»Дернуть блокирующую базу данных -»Использовать SDK без реактивной поддержки -»Делать .block(), потому что так проще В итоге: -»Все равно все становится блокирующим -»Ты просто добавил сложности -»Ничего не выиграл WebFlux не превращает блокирующий код в неблокирующий. А Virtual Threads разве это не меняют? Меняют, и это важно. С Virtual Threads: -»Блокирующая модель снова становится жизнеспособной -»Цена ожидания резко падает -»Необходимость в WebFlux уменьшается Но есть нюанс. Virtual Threads не дают: -»Backpressure -»Контроль потока -»Композицию стримов -»Настоящий стриминг данных Они меняют tradeoff, но не убирают саму проблему. Когда WebFlux все еще имеет смысл WebFlux оправдан, когда: -»Нужен реальный backpressure -»Ты работаешь с непрерывными стримами (SSE, WebSockets) -»Есть fan-out из множества внешних вызовов -»Нужно явно контролировать поток данных По необходимости, а не потому что модно. Когда не стоит использовать WebFlux -»Классический CRUD -»Сложная бизнес-логика -»Команды без реактивного опыта -»Проекты, где читаемость важнее конкурентности -»Когда Virtual Threads решают задачу с меньшей когнитивной стоимостью WebFlux это другая модель исполнения. Если твоя проблема не в масштабной I/O-конкурентности, WebFlux тебе не поможет. А сегодня, с Virtual Threads, многим он уже просто не нужен. 👉 Java Portal