Библиотека джависта | Java, Spring, Maven, Hibernate
22.8K subscribers
2.31K photos
51 videos
47 files
3.33K links
Все самое полезное для Java-разработчика в одном канале.

Список наших каналов: https://t.me/proglibrary/9197

Для обратной связи: @proglibrary_feeedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Download Telegram
Java в Enterprise + AI Agents = Мощный стек

Крупный бизнес 2026 года активно внедряет AI, и ему нужны надёжные решения. Как встроить LLM-агента в экосистему Spring? Как обеспечить безопасность данных?

На курсе мы учим архитектурному подходу. Мы разбираем паттерны построения агентов, которые можно реализовать на любом языке (в том числе через Spring AI), или интегрировать Python-микросервисы в вашу Java-инфраструктуру. Реальные кейсы, разбор ошибок и фокус на Enterprise.

Ключевые темы:

— Паттерны надёжности (Retry, Fallback, Circuit Breaker) при работе с LLM.
— Интеграция с корпоративными Knowledge Base (RAG).
— Безопасность и контроль доступа (RBAC) в агентных системах.

Освоить проектирование AI-систем
✔️ SQL-тест: Фильтрация активных рекламных кампаний

Задача из реального интервью в Google 👇

📦 Задание

Вы аналитик Google Ads. Нужно найти все объявления, которые:

— Имеют статус 'active'
— Показов больше 500,000
— Обновлены в 2024 году

Таблица google_ads на картинке. Напишите SQL-запрос для фильтрации.

Ставьте → 🔥, если нравится формат. Если нет → 🤔

💬 Решения под спойлер. Сравним, какое будет лучше.

🐸 Библиотека собеса по Java

#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15🤔4👍3👏1
🎮 Инструментарий разработчика

Собрали самые популярные и эффективные инструменты на все случаи жизни.

💬 Какие инструменты используете в повседневной работе?

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏1😁1
🐳 Магия Docker CLI

Если ты перезапускаешь контейнер или лезешь внутрь через exec, чтобы посмотреть процессы. То эта команда для тебя. Она показывает все процессы за секунду → docker top.

🔹 Зачем это нужно

— Показывает запущенные процессы внутри контейнера без входа в него.
— Видно PID, пользователя, нагрузку на CPU и команду запуска.
— Полезно для мониторинга и быстрой диагностики проблем с производительностью.

🔹 Как использовать

— Базовый вывод: docker top container_id
— С кастомным форматом (как ps): docker top container_id aux
— Можно фильтровать по пользователю или искать конкретный процесс.
— Удобно в скриптах для автоматизации проверок.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥31
⚙️ YAML vs Properties: что выбрать для Spring Boot конфигурации?

Недавно в очередной раз столкнулся с холиваром: "Зачем ты переписал properties в yaml?" Давайте разбираться.

🔹 Properties — старая гвардия


spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=admin
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect


✔️ Читается IDE из коробки, нет проблем с отступами, работает везде и всегда.

Повторяющиеся префиксы превращают файл в лапшу, особенно когда конфига много.

🔹 YAML — современный подход

spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
password: secret
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect


✔️ Структурированность, читаемость, легко работать со списками и сложными объектами. Можно описать несколько профилей в одном файле через ---.

Чувствителен к отступам (один лишний пробел — и привет, ошибка на старте), нельзя использовать с @PropertySource.

🔹 Технические нюансы

— Парсинг и производительность: properties парсится через java.util.Properties (простой key-value), YAML требует SnakeYAML библиотеку. На старте приложения разница незаметна, но YAML чуть медленнее из-за построения объектной модели.

— Приоритет загрузки: Spring Boot загружает конфиги в порядке: application.properties → application.yml → application-{profile}.properties → application-{profile}.yml. Если есть оба формата, properties имеет приоритет над yaml для одинаковых ключей.

— Списки и массивы: в YAML естественная запись списков, в properties приходится использовать индексы.

— Placeholder resolution: оба формата поддерживают ${variable:default}, но в YAML нужно быть осторожным с экранированием двоеточий в URL.

— Невалидный синтаксис: properties молча проигнорирует строку без =, YAML упадёт с исключением при старте приложения — это и минус, и плюс одновременно.

@PropertySource ограничение: аннотация работает только с .properties, для YAML нужно писать кастомный PropertySourceFactory.

Что выбрать?

YAML для основной конфигурации приложения — структура и удобство работы со сложными объектами того стоят. Properties для специфичных кейсов: custom property sources с @PropertySource, legacy интеграции, простые CI/CD переменные, конфиги для библиотек без Spring контекста.

В production проектах часто вижу гибридный подход: application.yml для базовой структуры + application-{env}.properties для переопределения специфичных параметров окружения через environment variables.

💬 Какой формат и в каких кейсах предпочитаете?

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍144🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥18😁14💯9👍3🙏1
📈 Продвинутая Map

Если ты хоть раз создавал Map<String, List<String>>, то пост для тебя.

Признай, каждый когда-нибудь писал:

Map<String, List<String>> userTags = new HashMap<>();
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("premium");
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("verified");


Или ещё хуже:

if (!userTags.containsKey("user123")) {
userTags.put("user123", new ArrayList<>());
}
userTags.get("user123").add("premium");


Apache Commons Collections давно придумал MultiValuedMap.

🔹 Что это такое

MultiValuedMap<K, V> — это структура данных, которая позволяет хранить несколько значений для одного ключа. По сути, это Map<K, Collection<V>>, но с нормальным API.

MultiValuedMap<String, String> userTags = new ArrayListValuedHashMap<>();

userTags.put("user123", "premium");
userTags.put("user123", "verified");
userTags.put("user123", "early-adopter");

// Получаем все теги разом
Collection<String> tags = userTags.get("user123");
// [premium, verified, early-adopter]


Никаких computeIfAbsent, никаких проверок на null. Просто работает.

🔹 Что умеет

— Добавление без боли:
multiMap.put("key", "value1");
multiMap.put("key", "value2"); // не перезатирает предыдущее значение


— Массовые операции:
multiMap.putAll("user456", Arrays.asList("admin", "moderator"));


— Проверка наличия:
multiMap.containsMapping("user123", "premium"); // true/false


— Удаление конкретного значения:
multiMap.removeMapping("user123", "premium");


— Получение всех значений:
Collection<String> allTags = multiMap.values(); 
// все значения из всех ключей


🔹 Реализации

ArrayListValuedHashMap<K, V> — значения хранятся в ArrayList, порядок сохраняется, дубликаты разрешены
HashSetValuedHashMap<K, V> — значения хранятся в HashSet, без дубликатов

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23👍11👏21
💬 Обратная связь

В связи с последними новостями созрел вопрос. Где бы кроме тг вы могли читать наш канал?

Пишите в комменты/лайкайте чужие ответы, какие ещё платформы с подобным контентом вы используете сейчас или были бы готовы использовать в будущем вместо тг?

P.S. Никто пока никуда не переезжает, просто собираем информацию :)

🐸 Библиотека джависта

#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥1👏1
😮 Топ-вакансий для джавистов за неделю

Java developer — 250 000 ₽ — удалёнка

Java Backend Developer — от 250 000 ₽ — офис/гибрид (Москва, Санкт-Петербург)

Руководитель разработки (Java) — 350 000 —‍ 425 000 ₽ — гибрид (Москва)

➡️ Еще больше топовых вакансий — в нашем канале Java jobs
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1👏1
🚩 Pattern Matching в Switch

Раньше switch был ограничен примитивами и enum'ами. С Java 21 Pattern Matching стал стандартом, и это принципиально меняет подход к обработке полиморфных данных.

Что раньше:

Object obj = getObject();
String result;
if (obj instanceof String s) {
result = "String: " + s;
} else if (obj instanceof Integer i) {
result = "Int: " + i;
} else {
result = "Unknown";
}


✔️ Что теперь:

String result = switch (obj) {
case String s -> "String: " + s;
case Integer i -> "Int: " + i;
case null -> "Null!";
default -> "Unknown";
};


Но суть не в синтаксисе. Суть в гарантиях компилятора.

🔹 Охранные выражения (guarded patterns)

String classify(Object obj) {
return switch (obj) {
case String s when s.length() > 10 -> "Long string";
case String s -> "Short string";
case Integer i when i > 0 -> "Positive";
case Integer i -> "Non-positive";
case null -> "Null";
default -> "Other";
};
}


Условия when проверяются последовательно. Компилятор отслеживает полноту покрытия и недостижимый код. Поменяете порядок кейсов неправильно — получите ошибку компиляции.

🔹 Record patterns — деструктуризация на месте

record Point(int x, int y) {}

String describe(Object obj) {
return switch (obj) {
case Point(int x, int y) when x == y ->
"Diagonal point";
case Point(int x, int y) ->
"Point at (%d, %d)".formatted(x, y);
default -> "Not a point";
};
}


Распаковали record прямо в case. Никаких геттеров, никаких промежуточных переменных.

🔹 Sealed классы + pattern matching = полнота проверок

sealed interface Result permits Success, Failure {}
record Success(String data) implements Result {}
record Failure(String error) implements Result {}

String handle(Result result) {
return switch (result) {
case Success(String data) -> "Got: " + data;
case Failure(String error) -> "Error: " + error;
// default не нужен - компилятор знает все варианты
};
}


Компилятор гарантирует, что вы обработали все случаи. Добавите новый класс в sealed иерархию — код не скомпилится, пока не обработаете его.

🔼 Производительность

JIT оптимизирует pattern matching свитчи агрессивно. В бенчмарках разница с if-else цепочками от 2x до 10x в пользу switch в зависимости от количества веток.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍711👏1
🌐 Что происходит, когда вы вводите адрес сайта

Каждый раз, когда вы набираете https://example.com в браузере, за кулисами запускается целая цепочка событий.

1️⃣ Разбор адреса

Браузер делит URL на части:

▪️ https — протокол
▪️ example.com — домен
▪️ /page — путь к ресурсу

2️⃣ Поиск IP

Если IP не сохранён в кеше, браузер спрашивает DNS-сервер: «Где живёт example.com

3️⃣ Установление соединения

Создаётся TCP-соединение с сервером по IP и порту (80 для HTTP, 443 для HTTPS).

4️⃣ Запрос ресурса

Браузер отправляет HTTP-запрос: GET /page HTTP/1.1

5️⃣ Ответ сервера

Сервер возвращает HTML, CSS, JS и статус-код (например, 200 OK или 404 Not Found).

6️⃣ Рендеринг страницы

Браузер обрабатывает HTML, применяет стили и выполняет JavaScript.

7️⃣ Шифрование

Если сайт работает по HTTPS, соединение шифруется через SSL/TLS.

8️⃣ Кеширование

Браузер сохраняет ресурсы, чтобы при следующем визите всё грузилось быстрее.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122🔥1👏1
⚙️ RestTemplate vs WebClient

🔹 RestTemplate

javaRestTemplate restTemplate = new RestTemplate();
ResponseEntity<User> response = restTemplate.getForEntity(
"https://api.example.com/users/{id}",
User.class,
userId
);
User user = response.getBody();


✔️ Простота, привычность, работает из коробки. Идеален для простых CRUD операций.

Блокирующий I/O — поток висит и ждет ответа. При высоких нагрузках нужен большой thread pool. С 5.0 официально в maintenance mode.

🔹 WebClient

javaWebClient webClient = WebClient.create("https://api.example.com");
Mono<User> userMono = webClient.get()
.uri("/users/{id}", userId)
.retrieve()
.bodyToMono(User.class);


✔️ Неблокирующий I/O — поток освобождается и обрабатывает другие запросы. Отлично работает с реактивными стримами. Fluent API, удобная настройка retry, timeout, circuit breaker.

Кривая обучения — нужно понимать реактивные концепции (Mono, Flux). Сложнее дебажить, требует Project Reactor в зависимостях.

🔹 Технические нюансы

— Thread model: RestTemplate использует по потоку на запрос (blocking I/O). WebClient работает на event loop с малым числом потоков (по умолчанию CPU cores * 2).

— Performance: в синхронных сценариях разница минимальна. При параллельных запросах WebClient показывает x2-x5 прирост throughput за счёт эффективного использования потоков.

— Memory footprint: 1000 параллельных REST вызовов через RestTemplate = ~1000 МБ стека потоков. WebClient с той же нагрузкой — десятки МБ.

— Timeout configuration: RestTemplate требует настройки через ClientHttpRequestFactory. WebClient имеет встроенный .timeout(Duration) в цепочке вызовов.

— Error handling: RestTemplate выбрасывает исключения синхронно. WebClient возвращает Mono с ошибкой.

— Testing: RestTemplate легко мокается через MockRestServiceServer. WebClient требует понимания StepVerifier из reactor-test.

— Compatibility: RestTemplate работает везде. WebClient требует Spring WebFlux в classpath, даже если используешь его в обычном Spring MVC приложении.

Что выбрать?

WebClient если стартуешь новый проект, делаешь микросервисы с высокой нагрузкой, уже используешь reactive stack или планируешь масштабироваться. RestTemplate если поддерживаешь legacy код без реактивности, команда не знакома с Project Reactor, делаешь простой CRUD сервис с малой нагрузкой.

Главное помни: преждевременная оптимизация — корень зла. Если RestTemplate закрывает задачу, не усложняй. Но если упираешься в потоки на проде, время учить реактивщину.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥32👏1
Собираем фулл-хаус: 3 курса по цене 1

Хватит выбирать между «полезно», «модно» и «для души». Мы запустили механику, которая позволяет собрать кастомный стек навыков без удара по бюджету: покупаете один курс — два других забираете бесплатно.

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

Для тех, кто смотрит в сторону Data Engineering или ML — полный набор по AI: от математики и ML-старта до разработки автономных агентов.

Ну и классика: обновлённый Python как удобный инструмент для вспомогательных скриптов.

Собрать свой пак
🤫 Spring 4.2+: события без наследования ApplicationEvent

Начиная с Spring 4.2 (2015 год!), классы событий больше не обязаны наследовать ApplicationEvent.

🔹 До Spring 4.2:

public class UserCreatedEvent extends ApplicationEvent {
private final String username;

public UserCreatedEvent(String username) {
this.username = username;
}

public String getUsername() {
return username;
}
}


🔹 Начиная с Spring 4.2+:

// Просто POJO
public class UserCreatedEvent {
private final String username;

public UserCreatedEvent(String username) {
this.username = username;
}
// getters...
}


🔹 Использование идентично:

@Service
public class UserService {

@Autowired
private ApplicationEventPublisher publisher;

public void createUser(String username) {
publisher.publishEvent(new UserCreatedEvent(username));
}
}

@EventListener
public void onUserCreated(UserCreatedEvent event) {
log.info("User created: {}", event.username());
}


Использование обычных POJO-классов в качестве событий делает код независимым от Spring Framework, что улучшает тестируемость и переносимость приложения.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍42🤔2
✔️ Spring-тест: @RateLimit аннотация для методов

Напишите production-ready Spring компонент 👇

📦 Задание

Реализуйте кастомную аннотацию @RateLimit, которая ограничивает количество вызовов метода с использованием Spring AOP.

🔹 Требования

— Использовать Spring AOP
— Потокобезопасность
— Кэш лимитов
— Учитывать имя метода + параметры
— Custom exception при превышении

Ставьте → 🔥, если нравится формат. Если нет → 🤔

💬 Решения под спойлер. Сравним, какое будет лучше.

🐸 Библиотека собеса по Java

#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥222👍2👏1🤔1
👑 Магия IntelliJ IDEA: множественные курсоры

Нужно изменить одинаковый код в 10 местах? Обычно делаешь Find & Replace или правишь вручную каждую строку. Есть способ быстрее — Multiple Cursors. Редактируешь несколько мест одновременно.

🔹 Что это

Несколько курсоров в редакторе. Печатаешь один раз — изменения применяются везде сразу. Как Vim visual block mode, но удобнее.

🔹 Как использовать

— Alt+J (Win/Linux) или Ctrl+G (Mac) — выделить следующее вхождение слова под курсором
— Alt+Shift+J — убрать последний курсор
— Ctrl+Alt+Shift+J — выделить ВСЕ вхождения сразу
— Alt+Shift+Click — поставить курсор мышью
— Alt+Shift+Insert → Column Selection Mode — выделение столбцом

🔹 Зачем это нужно

— Массовое редактирование без регулярок
— Быстрее Find & Replace для простых случаев
— Видишь изменения сразу, контролируешь процесс

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥51👏1😁1
This media is not supported in your browser
VIEW IN TELEGRAM
🔼 Прокачай DevOps-скиллы на практике

Платформа с реальными DevOps-задачами. Кейсы по Linux, Docker и Kubernetes — всё как в бою, но с читами:

✔️ Автопроверка решений
✔️ Подсказки
✔️ Готовые решения

🔗 Попробовать

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏1
🔬 Правильный вопрос про AI

Все исследования AI-ассистентов меряют одно: насколько быстрее ты закрываешь задачу. Метрика удобная, но она игнорирует 70–80% реальных затрат — поддержку, рефакторинг, устранение дефектов.

Исследование «Echoes of AI» (arXiv, 2025) спросило другое:

«Что будет, когда другой разработчик возьмёт AI-код и попытается его развивать?»

151 участник, 95% практикующие разработчики (не студенты). Java/Spring Boot проект, две фазы, настоящее РКИ. Одна группа пишет с AI, другая без. Потом третья группа без AI поддерживает и тот, и другой код.

Результат оказался неожиданный.

👉 Читать

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61🔥1