Java Portal | Программирование
12.3K subscribers
1.34K photos
108 videos
42 files
1.35K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Java: используй ReentrantReadWriteLock, если у тебя частые чтения и мало записей.

ReentrantReadWriteLock это утилита конкурентности в Java, которая дает два типа локов:

1. Read lock (лок на чтение): позволяет нескольким потокам читать одновременно, пока ни один поток не пишет.

2. Write lock (лок на запись): позволяет писать только одному потоку и блокирует всех остальных читателей и писателей, пока лок не будет освобожден.

Используй ReentrantReadWriteLock, когда:

1. Твой код часто читает разделяемые данные.

2. Записи происходят редко.

3. Ты хочешь выжать максимум параллелизма: разрешить нескольким читателям работать одновременно, но гарантировать, что запись идет строго эксклюзивно.

Пример:

public class SharedValue {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private int value = 0;

public int readValue() {
lock.readLock().lock();
try {
return value;
} finally {
lock.readLock().unlock();
}
}

public void writeValue(int newValue) {
lock.writeLock().lock();
try {
value = newValue;
} finally {
lock.writeLock().unlock();
}
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63
Что такое BeanPostProcessor в Java Spring Boot?

Это интерфейс, который позволяет вмешиваться в процесс создания и инициализации бинов в Spring-контейнере.

Он предоставляет два основных метода, которые вызываются на разных этапах жизненного цикла бина:

1. postProcessBeforeInitialization(Object bean, String beanName)
Вызывается до инициализации бина (до вызова метода с @PostConstruct или InitializingBean#afterPropertiesSet).

2. postProcessAfterInitialization(Object bean, String beanName)
Вызывается после инициализации бина (после того, как все методы инициализации завершились).

Зачем нужен BeanPostProcessor?

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

Примеры:

- Добавление проксирования бинов (например, для AOP или транзакций)
- Валидация или изменение свойств бина
- Логирование жизненного цикла
- Добавление кастомных аннотаций
- Обработка marker-интерфейсов

Как это работает?

1. Spring сканирует контекст на наличие бинов, которые реализуют интерфейс BeanPostProcessor.
2. Если такие бины найдены, они применяются ко всем бинам в приложении.
3. Методы postProcessBeforeInitialization и postProcessAfterInitialization вызываются для каждого бина, который создаёт Spring.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
8
Java-совет: начиная с Java 9 можно использовать Stream.takeWhile() для удобной "нарезки" списков через стримы.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);

✗ Вместо:

List<Integer> result = new ArrayList<>();

for (Integer n : numbers) {
if (n < 5) {
result.add(n);
} else {
break;
}
}
System.out.println(result); // [1, 2, 3, 4]

✓ Можно так:

result = numbers.stream().takeWhile(n -> n < 5).toList();
System.out.println(result); // [1, 2, 3, 4]


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥3
Я побывал по обе стороны собеседований по system design.

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

1. [Сервер]

2. [Задержка и пропускная способность]

3. [Масштабирование и его виды]
– Вертикальное и горизонтальное масштабирование

4. [Автомасштабирование]

5. [Прикидочные расчеты]

6. [Теорема CAP]

7. [Масштабирование базы данных]
– Индексы
– Партиционирование
– Архитектура master-slave
– Multi-master
– Шардирование базы данных
– Недостатки шардирования

8. [SQL и NoSQL базы данных и когда что использовать]

9. [База данных]
– SQL-база данных
– NoSQL-база данных
– Масштабирование в NoSQL и SQL
– Когда какую базу использовать?

10. [Микросервисы]
– Монолит vs микросервисы
– Зачем вообще разбивать приложение на микросервисы?
– Когда использовать микросервисы?
– Как клиенты делают запросы в микросервисной архитектуре?

11. [Глубокое погружение в load balancer]
– Зачем нужен load balancer?
– Алгоритмы load balancing

12. [Кеширование]
– Плюсы кеширования
– Типы кешей
– Redis

13. [Blob Storage]
– Что такое blob и зачем нужно blob storage?
– AWS S3

14. [CDN, Content Delivery Network]
– Как работает CDN?

15. [Message Broker]
– Асинхронное программирование
– Зачем ставить message broker между сервисами?
– Очередь сообщений
– Поток сообщений
– Когда использовать message broker

16. [Глубокое погружение в Apache Kafka]
– Когда использовать Kafka
– Внутреннее устройство Kafka

17. [Pub/sub в реальном времени]

18. [Event-Driven Architecture]
– Зачем использовать EDA?
– Простое уведомление о событии
– Передача состояния через событие

19. [Распределенные системы]

20. [Самовосстанавливающаяся система с election лидера]

21. [Глубокое погружение в consistency]
– Строгая согласованность
– Когда выбирать strong consistency
– Eventual consistency
– Когда выбирать eventual consistency
– Способы добиться strong consistency
– Способы добиться eventual consistency

22. [Consistent hashing]

23. [Избыточность данных и восстановление данных]
– Зачем делать базы данных избыточными?
– Разные способы резервного копирования
– Непрерывная избыточность

24. [Прокси]
– Forward proxy vs reverse proxy

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥1
Совет по Spring Boot: ускорить приложение можно с помощью @EnableCaching и @Cacheable.

🟢Позволяет избежать повторных вызовов к БД и API
🟢 Снижает задержки
🟢 По умолчанию Spring использует in-memory map, но в проде можно подключить внешний провайдер кеша

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
API Gateway, если по-человечески:

Клиент не должен ходить в 6 разных сервисов.
Он должен ходить в одну точку.

Gateway стоит перед всей системой и берёт на себя:

- маршрутизацию входящих запросов в нужный сервис
- валидацию токенов, например JWT и OAuth, ещё до того, как запрос вообще дойдёт до сервисов
- rate limiting, чтобы API не абьюзили
- логирование, чтобы наблюдаемость была в одном месте
- балансировку нагрузки между инстансами сервисов

Без gateway каждый сервис заново городит у себя аутентификацию, логирование и rate limiting.
С gateway всё это решается один раз, централизованно.

Вот и вся суть: одна точка входа и единый слой контроля.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍103
Не используйте ELSE 0 вместе с COUNT и CASE

Использование ELSE 0 - очень частая ошибка у новичков, когда они комбинируют функцию COUNT с выражением CASE. Обычно это происходит из-за непонимания того, как именно COUNT работает при применении к столбцу.

Когда используется COUNT(column), функция считает все значения, которые не равны NULL, включая нули. Это значит, что если в выражении CASE указан ELSE 0, каждая строка, не попавшая под условие, превращается в значение 0. В результате такие строки тоже попадают в подсчёт.

Вот наивный пример:

sql id="g4suvd"
SELECT
Department,
COUNT(CASE
WHEN Status = 'Active' THEN EmployeeID
ELSE 0
END) AS ActiveEmployees
FROM Employees
GROUP BY Department;


В этом запросе каждая строка, которая не удовлетворяет условию, превращается в 0, а это валидное значение, поэтому оно тоже учитывается в COUNT. Из-за этого результат может получиться вводящим в заблуждение.

Лучше всего вообще убрать ELSE. Когда ветка ELSE опущена, выражение CASE возвращает NULL для строк, которые не соответствуют условию. А так как COUNT() игнорирует NULL, будут посчитаны только строки, которые действительно удовлетворяют условию. Вот правильный вариант:

sql id="vxa5np"
SELECT
Department,
COUNT(CASE
WHEN Status = 'Active' THEN EmployeeID
END) AS ActiveEmployees
FROM Employees
GROUP BY Department;


В этой версии строки, не подходящие под условие, возвращают NULL, и COUNT() естественным образом исключает их из подсчёта. В итоге запрос получается чище, а подсчёт корректно отражает только те значения, которые реально соответствуют условию.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3
Java tip: используйте ThreadLocal.withInitial(...), чтобы у каждого потока было свое безопасное значение по умолчанию.

Значение создается лениво

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4
Вопрос на Java-собеседовании:

Что такое Spring Bean Scope?

Spring Bean Scope определяет жизненный цикл и область видимости бина в контейнере.

Основные типы:

- singleton (по умолчанию) — один экземпляр на весь контейнер.
- prototype — новый экземпляр для каждого запроса.
- request — бин живет в рамках одного HTTP-запроса.
- session — бин живет в рамках одной HTTP-сессии.
- application — бин живет в рамках всего веб-приложения.
- websocket — бин живет на протяжении сессии WebSocket.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4
Гайд для новичков по созданию HTTP-сервера с нуля.

Хочешь своими руками написать HTTP-сервер и потом отправлять на него запросы и получать ответы?
Если да, вот как раз гайд, по которому можно пройтись.

Что нужно знать заранее

Нужно знать Java.
Если не знаешь, не страшно: шаги из гайда можно перенести почти на любой язык, с которым тебе удобно работать, просто используя семантически эквивалентные конструкции в коде.

Примечание: JS/TS для этого гайда я бы не рекомендовал.


Базовое понимание программирования и OOP.

Текстовый редактор и, возможно, много кофе. Как пойдет. 🤭

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Совет по Java: List.reversed() возвращает неизменяемое (unmodifiable) представление исходного списка в обратном порядке.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4
This media is not supported in your browser
VIEW IN TELEGRAM
Трюк, чтобы сэкономить место на диске и время при клонировании репозиториев из GitHub.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Совет по Java : не полагайся полностью на сборщик мусора — утечки памяти всё ещё возможны.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥2
Типы классов в Java:

1. Concrete Class (конкретный класс) — обычный класс с полной реализацией методов.

2. Abstract Class (абстрактный класс) — не может быть создан через new; может содержать абстрактные методы.

3. Final Class (финальный класс) — не может быть унаследован.

4. Static Class (вложенный статический класс) — статический внутренний класс внутри другого класса.

5. Inner Class (внутренний класс) — нестатический класс, объявленный внутри другого класса.

6. Local Class (локальный класс) — класс, определённый внутри метода.

7. Anonymous Class (анонимный класс) — класс без имени, обычно используется для кратковременных реализаций.

8. Singleton Class (синглтон-класс) — гарантирует существование только одного экземпляра класса.

9. POJO (Plain Old Java Object) — простой Java-класс без специальных ограничений или требований.

10. Record Class (Java 14+) — компактный класс для представления неизменяемых данных.

11. Enum Class (класс-перечисление) — определяет фиксированный набор констант.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92🤔1
💡Java tip: Начиная с Java 14 можно использовать switch-выражения, чтобы писать более короткую и чистую мультиветвящуюся логику.

// Old way:
String season;
switch (month) {
case 12:
case 1:
case 2:
season = "Winter";
break;
case 3:
case 4:
case 5:
season = "Spring";
break;
default:
season = "Invalid";
}

// New switch expression:
String season = switch (month) {
case 12, 1, 2 -> "Winter";
case 3, 4, 5 -> "Spring";
default -> "Invalid";
};
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥85👍3👀1
Совет по Spring AI

Запускаете локальные AI-модели через LM Studio и сталкиваетесь с зависанием соединения, когда ваше приложение Spring AI вызывает API, совместимый с OpenAI?

LM Studio не поддерживает HTTP/2, из-за чего запрос может зависать.

Решение: отключить HTTP/2 для`RestClient`.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Spring Boot: Используйте spring.mvc.publish-request-params=true только в dev-среде. Это опасно в production.

В production логирование деталей запроса может привести к раскрытию чувствительной информации.

Когда вы настраиваете свойства Spring-приложения в dev со следующими параметрами:

# Включить публикацию параметров
spring.mvc.publish-request-params=true

# Установить уровни логирования, чтобы видеть вывод
logging.level.org.springframework.web=DEBUG
logging.level.org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor=DEBUG


и конфигурацию фильтра примерно такую:

@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true); // 2) Query-параметры
filter.setIncludeHeaders(true); // 1) Заголовки запроса
filter.setIncludePayload(true); // 3) Данные формы
filter.setMaxPayloadLength(1000);
filter.setAfterMessagePrefix("COMPLETE REQUEST: ");
return filter;
}


вы включаете логирование:

1. заголовков запроса (Request headers)
2. query-параметров (Query parameters)
3. данных формы (Form data)

Без этого Spring маскирует или опускает многие из этих деталей, чтобы избежать утечки информации.

Не используйте это в production, иначе вы раскроете чувствительную информацию, например пароли:

POST /login
Body: {"username":"john","password":"mypassword"}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42
Вопрос на собеседовании по Git:

Ваша основная ветка (main) опережает вашу локальную ветку.

Как обновить свою ветку, не затронув ваши коммиты?

git fetch
Скачивает последние изменения из удалённого репозитория, не изменяя ваши локальные коммиты.

git rebase origin/main
Перенакладывает (reapply) ваши коммиты поверх обновлённой ветки main, сохраняя чистую историю коммитов.

До rebase:

A --- B --- C  (origin/main)
\
D --- E (ваша ветка)


После rebase:

A --- B --- C --- D --- E


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍143🤔1
Совет по Java 💡: используйте Files.walk() для рекурсивной обработки файлов в директории.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥10👍42
Обход правила WAF в CloudFront, которое блокирует доступ к Spring Boot.

Все обходы возвращают реальные данные Actuator:

GET /%61ctuator/health    → HTTP 200 (5122B) ← 'a' закодирована
GET /a%63tuator/health → HTTP 200 (5123B) ← 'c' закодирована
GET /ac%74uator/health → HTTP 200 (5122B) ← 't' закодирована
GET /act%75ator/health → HTTP 200 (5123B) ← 'u' закодирована
GET /actu%61tor/health → HTTP 200 (5123B) ← 'a' закодирована
GET /actua%74or/health → HTTP 200 (5123B) ← 't' закодирована
GET /actuat%6For/health → HTTP 200 (5123B) ← 'o' закодирована
GET /actuato%72/health → HTTP 200 (5123B) ← 'r' закодирована
GET /a%63%74uator/health → HTTP 200 (5123B) ← двойное кодирование
GET /%61ctua%74or/health → HTTP 200 (5123B) ← двойное кодирование
GET /%61%63%74%75%61%74%6F%72/health → HTTP 200 (5122B) ← полностью закодировано


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2