TGViewer
Channel Public Channel
Библиотека джависта | Java, Spring, Maven, Hibernate

Библиотека джависта | Java, Spring, Maven, Hibernate

@javaproglib

Все самое полезное для Java-разработчика в одном канале.

Учиться у нас: clc.to/AATM8w

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

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

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Subscribers
22K
Photos
2.5K
Videos
57
Links
3.7K

Showing posts older than #7517 · Back to latest

Older Posts 20 shown
Post #7516 2.44K
Почитали тут свежий отчёт по рынку ИИ-ускорителей в РФ: оказывается, 54% компаний тормозят внедрение ИИ исключительно из-за конских цен на инфраструктуру.

Ну, то есть написать пет-проект с вызовом API это задача на вечер, а вот запустить агента в продакшн так, чтобы он не сжёг бюджет отдела за неделю — суровая инженерия.

По сути, сейчас мало уметь собирать RAG. Нужно считать токены, настраивать time-travel дебаг в LangGraph и уметь роутить запросы на лету. Всё это мы учли в обновлённом курсе по разработке AI-агентов, где акцент сделан именно на AgentOps и жёсткий контроль ресурсов.

Также в программе:

— оценка качества, трейсинг и защита от деградации пайплайнов;
— мультиагентные паттерны и интеграция по протоколу MCP;
— локальный деплой Open Source под 152-ФЗ (когда данные нельзя выносить наружу).

Кажется, это единственный адекватный roadmap по переходу от блокнотов к enterprise-решениям.

Прямо сейчас можно урвать курс с увесистой скидкой (49 000 ₽ 62 990 ₽ за базовый тариф и 99 000 ₽ 124 990 ₽ за продвинутый трек), но стоит поторопиться — на потоке осталось всего 5 мест.

👉 Зафиксировать цену и начать собирать агентов, за которых не стыдно в проде
Post #7515 2.19K
🌐 Зачем нужен CDN и как он работает

Когда пользователь из Сиднея открывает ваш сайт, его запрос летит на сервер в Германии и обратно. Это ~300 мс только на «дорогу» — и это для каждого изображения, шрифта, JS-файла.

CDN (Content Delivery Network / Сеть доставки контента) решает эту проблему в лоб: вместо одного сервера — тысячи точек по всему миру. Пользователь получает файлы с ближайшей к нему ноды, а не с вашего origin-сервера.

🔹 Origin и Edge

В архитектуре с CDN появляются два новых понятия:

— Origin Server (Главный сервер): это ваш настоящий сервер, где крутится Spring Boot, лежит база данных и хранятся оригиналы всех файлов (например, в Amazon S3).

— Edge Servers (Граничные серверы / Точки присутствия - PoP): это тысячи серверов CDN-провайдера (например, Cloudflare или Akamai), раскиданные по всему земному шару: в Сиднее, Токио, Нью-Йорке, Лондоне, Москве.

🔹 Как работает кэш

Первый запрос к конкретному файлу всё равно идёт до origin. CDN его скачивает, кэширует у себя и отдаёт пользователю. Все последующие запросы на тот же файл edge-сервер обрабатывает сам, не трогая ваш бэкенд. Это называется cache hit.

🔹 Что кладем в CDN

CDN идеально подходит для статического контента:

— Картинки, видео, аудио.
— Скомпилированные файлы JavaScript и CSS.
— Шрифты.

CDN не подходит для динамического контента:

— Корзина товаров.
— Приватные данные пользователя.
— (Запросы к API /api/v1/users/me должны идти напрямую на ваш сервер, минуя кэш CDN).

🔹 Защита от DDoS

Современные CDN (тот же Cloudflare) - это не просто кэш. Это гигантский щит.

Если хакеры решат «положить» ваш сайт и отправят миллион запросов в секунду, этот удар примут на себя серверы CDN. Их пропускная способность измеряется терабитами. Они отфильтруют «мусорный» трафик, и ваш маленький Origin-сервер даже не заметит атаки.

🔹 Побочные эффекты

— Ускорение: пользователи получают тяжелый контент мгновенно, потому что скачивают его из своего же города.

— Экономия: ваш главный сервер больше не тратит процессорное время и трафик на отдачу терабайтов картинок. Вы платите за сервера меньше.

— Безопасность: CDN скрывает реальный IP-адрес вашего сервера и защищает от DDoS-атак.

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

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

#CoreJava
  • 👍 5
  • ❤ 4
  • 🔥 1
Post #7513 2.5K
🔐 Security-модуль за 5 минут с AI

Каждый раз одно и то же: новый проект, пишешь JWT с нуля, лезешь в старые репозитории за шаблоном, получаешь deprecated код на Spring Security 5.

Можно иначе — сформулировал промпт так, чтобы AI сразу выдал то, что не придётся переписывать.

Ты Senior Java-разработчик. Сгенерируй production-ready модуль безопасности для Spring Boot 3.x.

Требования:
- JWT (access + refresh токены), фильтр OncePerRequestFilter
- SecurityFilterChain: csrf off, session stateless
- UserDetailsService через JPA-репозиторий
- Пакеты: security/config, security/filter, security/service
- Обработка AuthenticationException и AccessDeniedException — отдельные handler-классы
- Никакого WebSecurityConfigurerAdapter

Стек: Java 21, Spring Boot 3.2, Spring Security 6, JJWT 0.12.x

Верни полный код всех классов с import и package.


Дальше подгоняешь под свою модель пользователя и роли. Основа готова.

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

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

#Enterprise
  • 👍 9
  • 🔥 2
  • 🌚 1
Post #7510 2.68K
🖥 Паттерны ООП c примерами

Многие из нас знают паттерны «по названиям». Но можешь ли объяснить, чем AbstractFactory отличается от FactoryMethod? Или когда Prototype — не оверинжиниринг, а реальное решение?

На Хабре вышла первая часть добротного разбора порождающих паттернов с примерами. Без воды, с живыми примерами на Kafka vs RabbitMQ, Spring @Component, Lombok @Builder.

👉 Читать на Хабре

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

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

#CoreJava
  • ❤ 7
  • 👍 5
  • 🔥 1
Post #7509 2.42K
😮 Топ-вакансий для джавистов за неделю

Java Developer — ЮMoney — удалёнка

Java-разработчик — DUC Technologies — удалёнка

Senior Java Developer — Лектон — удалёнка/гибрид (Санкт-Петербург)

➡️ Еще больше топовых вакансий — в нашем канале Java jobs
  • ❤ 2
  • 👍 1
Post #7508 2.51K
🏭 Паттерн Factory Method

Factory Method — это порождающий паттерн, который предоставляет интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов.

Использование

🔹 Когда тип создаваемого объекта зависит от контекста или конфигурации.
🔹 Когда нужно расширять систему новыми продуктами без правки существующего кода.
🔹 Когда создание объекта — это не просто new, а логика с условиями.

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

1️⃣ Ослабление связи между кодом и конкретными классами

При прямом вызове new вы жёстко привязаны к конкретному классу. Если его нужно заменить — придётся найти и исправить все точки создания. Фабрика убирает эту зависимость: код работает через интерфейс, конкретная реализация подставляется в одном месте.

2️⃣ Централизованное управление созданием объектов

Фабрика может содержать нетривиальную логику:

▪️ Выбор нужного класса в зависимости от условий.
▪️ Управление жизненным циклом объекта.
▪️ Применение Singleton или Object Pool внутри фабрики.

3️⃣ Расширяемость без правки существующего кода

Новый тип продукта — новый подкласс. Основной код не трогаете. Это и есть принцип Open/Closed в действии.

4️⃣ Упрощение тестирования

Фабрику можно подменить в тестах — подсунуть mock-реализацию. Это чище, чем патчить конструктор или использовать статические методы.

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

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

#CoreJava
  • ❤ 6
  • 👍 5
  • 👾 2
  • 🔥 1
Post #7506 1.98K

Forwarded from Библиотека собеса по Java | вопросы с собеседований

❓ Какие уровни изоляции транзакций существуют?

Существует 4 основных уровня изоляции транзакций, каждый из которых определяет степень видимости данных, изменённых в одной транзакции, для других транзакций:

🔹 READ UNCOMMITTED

Наименьший уровень изоляции. Другие транзакции могут читать изменения, которые ещё не были зафиксированы (не коммитнуты). Это может привести к грязным чтениям.

🔹 READ COMMITTED

Транзакция видит только те изменения, которые были зафиксированы другими транзакциями. Это предотвращает грязные чтения, но допускает неповторяемые чтения.

🔹 REPEATABLE READ

Гарантирует, что данные, считанные в рамках одной транзакции, не изменятся до её завершения (не допускаются неповторяемые чтения). Однако, могут возникать фантомные чтения.

🔹 SERIALIZABLE

Все транзакции выполняются последовательно, как если бы они были выполнены по очереди.

Реализуется через блокировки (Lock-based): БД ставит range locks — блокирует не только существующие строки, но и диапазоны, куда могут вставиться новые. Это устраняет все виды аномалий, но может значительно снизить производительность.


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

#concurrency
  • 🔥 6
  • 👍 4
  • ❤ 2
Post #7505 2.19K
Кажется, мы окончательно перешли от игрушек к суровому AgentOps

Приглашаем на наш обновлённый курс по разработке ИИ-агентов. Никакой воды про «будущее нейросетей», только инженерный подход.

На курсе мы:

— пошагово строим готовые системы на LangGraph, CrewAI и MCP;
— настраиваем кэширование и роутинг, чтобы бот не сожрал токены;
— разбираемся со стейтом, учимся дебажить через time-travel и прикручиваем human-in-the-loop;
— выводим RAG в прод так, чтобы безопасники не завернули архитектуру из-за 152-ФЗ.

В пекло скучные лекции про общую инфраструктуру — сразу фокусируемся на агентных фреймворках и написании кода. Занятия ведут бывалые лиды из Газпромбанка и Альфы, набившие шишки на реальных задачах.

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


Сегодня последний день, когда можно забрать курс по старым ценам. Базовый тариф сейчас стоит 49 000 ₽ (вместо 62 990 ₽), продвинутый трек — 99 000 ₽ (вместо 124 990 ₽). Если не хочется отдавать всю сумму сразу, есть рассрочка. Торопитесь — на потоке осталось всего 5 мест!

→ Зафиксировать цену и перейти к сборке своих агентов
  • 😢 1
Post #7504 2.15K
У «Библиотеки программиста» появился резервный канал в мессенджере MAX

Он нужен исключительно для связи с теми, кто не может следить за обновлениями здесь из-за трудностей с доступом. Поэтому, если вы видите это сообщение, распространите его среди жильцов вашего ЖЭКа.

Контент в MAX будет дублировать телеграмный — основной нашей площадкой был и остаётся Telegram. Надеемся, это временная мера.

→ Подписаться на «Библиотеку программиста» в MAX
  • 😢 19
  • 🌚 4
  • 😁 3
  • 🥱 1
Post #7503 2.21K
🧵 Просто о сложном: ThreadLocal

В многопоточном приложении потоки разделяют общую память. Это создаёт проблемы с состоянием. ThreadLocal решает это элегантно — каждый поток получает свою копию переменной.

🔹 Как устроено внутри

Никакой центральной Map на уровне JVM нет. Всё проще: у каждого объекта Thread есть поле threadLocals типа ThreadLocal.ThreadLocalMap. Это внутренняя Map, которая живёт внутри самого потока.

Когда ты вызываешь set() — значение кладётся в Map текущего потока, где ключ — сам объект ThreadLocal:
// упрощённо, внутри ThreadLocal.set(value)
Thread.currentThread().threadLocals.put(this, value);

get() — достаёт из Map того же потока. Другой поток обращается к своей Map и видит своё значение. Пересечений нет по конструкции.

🔹 Инициализация через withInitial

Если get() вызван, а set() ещё не было, возвращается null. Чтобы этого избежать, используют фабрику:
ThreadLocal<SimpleDateFormat> sdf =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

Лямбда вызовется один раз на поток, при первом get(). Дальше кешируется в той же threadLocals Map.

🔹 Что реально использует ThreadLocal в экосистеме

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

→ TransactionSynchronizationManager — текущее соединение с БД, чтобы сервис и репозиторий в рамках @Transactional работали с одним коннектом
→ SecurityContextHolder — аутентифицированный пользователь
→ RequestContextHolder — текущий HttpServletRequest

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

🔹 Где ломается

Thread Pool. Потоки переиспользуются и после обработки запроса поток возвращается в пул, но его threadLocals Map никуда не девается. Если не вызвать remove(), то следующий запрос, попавший в этот поток, найдёт чужие данные.

Это не гипотетическая проблема. Именно так утекают security-контексты и появляются баги, которые воспроизводятся только под нагрузкой.

Второй момент — утечка памяти. ThreadLocalMap использует WeakReference на ключ, но значение держится сильной ссылкой. Если поток живёт долго (а в пуле — фактически вечно) и remove() никто не вызвал — объект не будет собран GC, пока поток жив.

Поэтому паттерн всегда один:
try {
tl.set(value);
// работа
} finally {
tl.remove();
}


ThreadLocal решает конкретную задачу — изоляция состояния без синхронизации. Не серебряная пуля, не замена synchronized. Просто инструмент для случаев, когда данные должны жить в рамках потока, а не шариться между ними.

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

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

#CoreJava
  • 👍 7
  • ❤ 5
  • 🔥 2
Post #7502 2.23K
🔧 Micrometer: кастомные метрики которые реально полезны в production

Стандартные метрики Spring Boot (JVM, HTTP, datasource) — это база. Бизнес-метрики и метрики производительности конкретных операций пишутся вручную.

🔹 Решение

▪️ Базовые типы метрик

@Service
public class OrderMetrics {

private final Counter ordersCreated;
private final Counter ordersFailed;
private final Timer orderProcessingTime;
private final DistributionSummary orderAmountSummary;
private final AtomicInteger activeOrders;

public OrderMetrics(MeterRegistry registry) {
this.ordersCreated = Counter.builder("orders.created")
.description("Total orders created")
.tag("environment", "production")
.register(registry);

this.ordersFailed = Counter.builder("orders.failed")
.description("Total failed orders")
.register(registry);

this.orderProcessingTime = Timer.builder("orders.processing.time")
.description("Order processing duration")
.publishPercentiles(0.5, 0.95, 0.99)
.publishPercentileHistogram()
.sla(Duration.ofMillis(200), Duration.ofSeconds(1))
.register(registry);

this.orderAmountSummary = DistributionSummary.builder("orders.amount")
.description("Order amounts distribution")
.baseUnit("USD")
.publishPercentiles(0.5, 0.95)
.register(registry);

this.activeOrders = registry.gauge("orders.active",
new AtomicInteger(0));
}

public Order processOrder(OrderRequest request) {
activeOrders.incrementAndGet();
return orderProcessingTime.record(() -> {
try {
Order order = doProcess(request);
ordersCreated.increment();
orderAmountSummary.record(order.getAmount().doubleValue());
return order;
} catch (Exception e) {
ordersFailed.increment();
throw e;
} finally {
activeOrders.decrementAndGet();
}
});
}
}


▪️ Тег-стратегия для разрезания метрик


Timer.builder("external.api.calls")
.tag("service", "payment-gateway")
.tag("operation", "charge")
.tag("status", result.isSuccess() ? "success" : "failure")
.register(registry)
.record(duration);


В Grafana это даёт возможность делать rate(external_api_calls_total{status="failure"}[5m]) и смотреть ошибки по сервисам отдельно.

▪️ application.yml для Prometheus

management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 50ms,200ms,500ms,1s
tags:
application: ${spring.application.name}
environment: ${APP_ENV:local}


publishPercentileHistogram() — ключевая настройка для Timer. Без неё Prometheus получает только count/sum и заранее вычисленные перцентили. С ней — полную гистограмму, из которой Prometheus сам считает перцентили через histogram_quantile().

Это важно при агрегации метрик с нескольких инстансов: заранее вычисленные перцентили нельзя корректно агрегировать, гистограммы — можно.

⚠️ Каждая уникальная комбинация тегов создаёт отдельный time series в Prometheus. Теги с высокой кардинальностью (userId, orderId, IP-адрес) убивают Prometheus. Теги должны иметь конечное и небольшое множество значений.

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

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

#Enterprise
  • 👍 6
  • 🔥 1
  • 👏 1
Post #7498 2.73K
👑 Магия IntelliJ IDEA

IntelliJ IDEA может помочь с созданием тестов. С помощью Ctrl + Shift + T можно сгенерировать структуру тестов для классов и методов.

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

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

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

— Поместите курсор на класс или метод, для которого нужен тест.
— Нажмите Ctrl + Shift + T (на Windows/Linux) или Cmd + Shift + T (на macOS).
— Выберите, какой тестовый фреймворк использовать (JUnit, TestNG и т.д.), и IDEA предложит создать тестовый класс с нужной структурой.

IDE автоматически создаст тестовый класс с методами для проверки каждого (или выбранного) публичного метода.

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

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

#CoreJava
  • 👍 6
  • 🔥 4
  • ❤ 1
Post #7497 2.44K

Forwarded from Библиотека программиста

IntelliJ IDEA: The Documentary | An origin story 👩‍💻

Док рассказывает о 25-летнем пути одного из самых любимых инструментов в разработке софта. Благодаря редким архивным кадрам, эксклюзивным интервью и закулисным моментам в нем рассказывается о том, как IntelliJ IDEA бросила вызов существующему положению вещей.

Ты увидишь истории от создателей JetBrains, действующих инженеров и мнения представителей Google, Oracle и сообщества Spring.

🍿 Смотреть
❤️ Полная коллекция доков про различные популярные ЯП, технологии, библиотеки, фреймворки и инструменты

🐸 Библиотека программиста
  • ❤ 6
  • 👍 4
  • 🔥 2
Post #7496 2.66K
🖥 Тренажёр администрирования Linux-серверов

SadServers — это симулятор сисадмина и DevOps, где вы подключаетесь к реальному виртуальному серверу по SSH и чините настоящие проблемы, а не тестовые кейсы.

Как это выглядит

— Выдают сломанный сервер с конкретной задачей
— Заходите по SSH, находите причину и фиксите
— Есть таймер, не успели — сервер отключается

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

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

#Enterprise
  • ❤ 7
  • 👍 5
  • 😁 2
  • 🔥 1
Post #7495 2.24K

Forwarded from Библиотека собеса по Java | вопросы с собеседований

✔️ Java-тест: что не так с этим сервисом?

Код компилируется, тесты зелёные, в проде всё ломается 👇

📦 Задание — code review


Сервис обрабатывает заявки на вывод средств. Требования простые: нельзя выводить больше, чем есть на балансе, и нельзя создавать две заявки одновременно.

@Service
@RequiredArgsConstructor
public class WithdrawalService {

private final AccountRepository accountRepository;
private final WithdrawalRepository withdrawalRepository;

public void requestWithdrawal(Long userId, BigDecimal amount) {
Account account = accountRepository.findByUserId(userId)
.orElseThrow();

if (account.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException();
}

boolean hasPending = withdrawalRepository
.existsByUserIdAndStatus(userId, Status.PENDING);

if (hasPending) {
throw new WithdrawalAlreadyPendingException();
}

account.setBalance(account.getBalance().subtract(amount));
accountRepository.save(account);

withdrawalRepository.save(
new Withdrawal(userId, amount, Status.PENDING)
);
}
}


🔹 Задачи

Два запроса от одного пользователя прилетели одновременно. В итоге — баланс ушёл в минус и создались две заявки.

▪️ Объясни

— Точную последовательность событий при конкурентных запросах.
— Спасёт @Transactional над методом или нет? Почему?
— Как исправить это корректно.

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

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

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

#practise
  • 🔥 14
  • 👍 2
  • 🤔 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →