Spring Boot: чтобы при сериализации в Jackson исключать любые поля, у которых значение null, можно использовать аннотацию
Все пустые поля исключаются автоматически.
👉 Java Portal
@JsonInclude(Include.NON_NULL)@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserDTO {
private Long id;
private String name;
private String email;
private String phone;
...
}
Все пустые поля исключаются автоматически.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤3🤔2
Spring Boot: на этапе разработки используй spring.main.lazy-initialization=true, чтобы ускорить старт приложения.
По умолчанию Spring Boot жадно инициализирует все бины на старте. В дев-окружении это значит:
1. Дольше стартует, особенно в больших проектах
2. Приходится ждать загрузки бинов, которые тебе прямо сейчас не нужны
Чтобы этого избежать, в
Но в проде важно оставить дефолтное поведение, потому что:
1. Ошибки старта ловятся раньше
2. Все компоненты сразу готовы принимать запросы
👉 Java Portal
По умолчанию Spring Boot жадно инициализирует все бины на старте. В дев-окружении это значит:
1. Дольше стартует, особенно в больших проектах
2. Приходится ждать загрузки бинов, которые тебе прямо сейчас не нужны
Чтобы этого избежать, в
application.properties поставь:spring.main.lazy-initialization=true
Но в проде важно оставить дефолтное поведение, потому что:
1. Ошибки старта ловятся раньше
2. Все компоненты сразу готовы принимать запросы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3
This media is not supported in your browser
VIEW IN TELEGRAM
Сommand completion (..) расширяет обычный code completion. Помимо автодополнения API и postfix completion, автодополнение кода теперь включает и команды. Чтобы отфильтровать список только до команд, используйте
👉 Java Portal
.. Список поддерживает поиск, чтобы быстрее находить нужное.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Java tip : старайся не шарить данные между потоками.
✅ Используй immutable-объекты
✅ Или пусть потоки общаются сообщениями, не лезя напрямую в общий state и не мутируя его
👉 Java Portal
// With immutable objects:
record Book(String title, int price) {} //Immutable
public class BookJob implements Runnable {
private final Book book;
....//constructor
@Override
public void run() {
System.out.println(book.title() + " " + book.price());
}
}
// Exchanging messages:
...
new Thread(() -> {
try {
queue.put("mess1");
} catch (InterruptedException e) {}
}).start();
...
new Thread(() -> {
try {
String mess = queue.take();
} catch (InterruptedException e) {}
}).start();
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
10 золотых правил чистого кода:
1. Избегай магических чисел и строк
2. Используй осмысленные, говорящие имена
3. Предпочитай ранние
4. Избегай длинных списков параметров
5. Делай функции маленькими и сфокусированными
6. Соблюдай DRY (Don’t Repeat Yourself) — не дублируй код
7. Применяй принцип KISS (Keep It Simple, Stupid) — делай проще
8. Отдавай предпочтение композиции, а не наследованию
9. Комментируй только там, где это действительно необходимо
10. Пиши хорошие сообщения к коммитам
Какие еще правила чистого кода ты бы добавил в этот список?
👉 Java Portal
1. Избегай магических чисел и строк
2. Используй осмысленные, говорящие имена
3. Предпочитай ранние
return вместо глубокой вложенности4. Избегай длинных списков параметров
5. Делай функции маленькими и сфокусированными
6. Соблюдай DRY (Don’t Repeat Yourself) — не дублируй код
7. Применяй принцип KISS (Keep It Simple, Stupid) — делай проще
8. Отдавай предпочтение композиции, а не наследованию
9. Комментируй только там, где это действительно необходимо
10. Пиши хорошие сообщения к коммитам
Какие еще правила чистого кода ты бы добавил в этот список?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥6
Совет по Java: если нужна максимально хорошая производительность в общем случае, бери HashMap как реализацию Map.
✅
🪲 Он не потокобезопасный (если нужна thread-safety, используй
Пример:
👉 Java Portal
HashMap внутри реализован как хеш-таблица, и в среднем put(), get() и remove() работают за O(1).ConcurrentHashMap).Пример:
Map<String, Integer> ages = new HashMap<>();
// Добавляем данные
ages.put("Michael", 31);
ages.put("Lisa", 25);
ages.put("Alice", 42);
// Поиск
System.out.println("Возраст Lisa: " + ages.get("Lisa"));
// Удаление
ages.remove("Alice");
// Итерация
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤4💊1
This media is not supported in your browser
VIEW IN TELEGRAM
Если ты изучаешь Java или хочешь прокачать навыки, обрати внимание на JBook — это интерактивная книга по Java, доступная прямо на GitHub.
Что внутри:
🔸 Подробное объяснение основ языка Java;
🔸 Примеры кода с пояснениями;
🔸 Упражнения для закрепления знаний;
🔸 Поддержка Jupyter Notebook + Java (IJava kernel) — можно запускать код прямо в браузере
GitHub: https://github.com/qcha/JBook
👉 Java Portal
Что внутри:
GitHub: https://github.com/qcha/JBook
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥4
Java-совет: начиная с Java 14 можно использовать switch-выражения, чтобы писать многоветвистую логику короче и чище.
👉 Java Portal
// 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
👍17❤7
This media is not supported in your browser
VIEW IN TELEGRAM
Batch Processing vs Stream Processing: в чем разница?
Batch processing (пакетная обработка)
▪️ Обрабатывает данные большими порциями (батчами) по расписанию.
▪️ Отлично подходит для исторических данных, хранилищ (DWH) и аналитики.
▪️ Примеры: расчёт зарплаты, периодические отчёты, ETL/ELT джобы.
Плюсы: эффективно на больших объёмах, дешевле по ресурсам, хорошо оптимизируется под throughput
Минусы: высокая задержка (latency), не подходит для задач, где нужно “прямо сейчас”
⚙️ Инструменты: Apache Hadoop, Apache Spark, AWS Glue
Stream processing (потоковая обработка)
▪️ Обрабатывает данные непрерывно, по мере поступления.
▪️ Используется для real-time аналитики, антифрода, мониторинга “вживую”.
▪️ Примеры: мониторинг биржи, рекомендации в реальном времени, IoT-датчики.
Плюсы: низкая задержка, инсайты в реальном времени, реактивные системы
Минусы: сложнее в реализации и поддержке, требует высокой доступности и масштабируемости
⚙️ Инструменты: Apache Kafka, Apache Flink, Apache Storm, Spark Streaming
Во многих современных системах делают гибрид: batch для хранения и аналитики, stream для реакций и real-time сигналов.
👉 Java Portal
Batch processing (пакетная обработка)
Плюсы: эффективно на больших объёмах, дешевле по ресурсам, хорошо оптимизируется под throughput
Минусы: высокая задержка (latency), не подходит для задач, где нужно “прямо сейчас”
Stream processing (потоковая обработка)
Плюсы: низкая задержка, инсайты в реальном времени, реактивные системы
Минусы: сложнее в реализации и поддержке, требует высокой доступности и масштабируемости
Во многих современных системах делают гибрид: batch для хранения и аналитики, stream для реакций и real-time сигналов.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🔥2
Spring Boot: лучше не использовать wildcard-исключения для транзитивных зависимостей в POM-файлах, потому что они могут прятать проблемы.
Wildcard-исключения просто убирают симптом и маскируют реальную причину: несовпадение версий.
👉 Java Portal
Wildcard-исключения просто убирают симптом и маскируют реальную причину: несовпадение версий.
<!-- Так лучше НЕ делать: wildcard-исключение (фактически “вырубаем всё”) -->
<exclusions>
<exclusion>
<!-- * = любой groupId -->
<groupId>*</groupId>
<!-- * = любой artifactId -->
<artifactId>*</artifactId>
</exclusion>
</exclusions>
<!-- Лучше: исключать конкретную транзитивную зависимость явно -->
<exclusion>
<!-- точный groupId зависимости, которую исключаем -->
<groupId>org.apache.tomcat.embed</groupId>
<!-- точный artifactId зависимости, которую исключаем -->
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
Project Panama: как Java научилась говорить на C! (Часть 1)
Как безопасно и эффективно вызывать C-функции из Java? Благодаря Project Panama — новому API из OpenJDK — это стало возможно без использования JNI.
👉 Java Portal
Как безопасно и эффективно вызывать C-функции из Java? Благодаря Project Panama — новому API из OpenJDK — это стало возможно без использования JNI.
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Project Panama: как Java научилась говорить на C! (Часть 1)
Как безопасно и эффективно вызывать C-функции из Java? Благодаря Project Panama — новому API из OpenJDK — это стало возможно без использования JNI. В новом переводе от команды Spring АйО познакомимся...
🤯3❤1
This media is not supported in your browser
VIEW IN TELEGRAM
Защищаю своё Spring Boot Java-приложение, которое использует 64 ГБ оперативной памяти, чтобы вернуть { "status": "ok" }
👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁31
Spring Boot: держи контроллеры тонкими, логику выноси в сервисы.
Главная задача контроллера, по сути, только разрулить HTTP-часть.
Плохой пример: бизнес-правила запихнуты в контроллер, типа проверки остатков и лимита заказа:
👉 Java Portal
Главная задача контроллера, по сути, только разрулить HTTP-часть.
Плохой пример: бизнес-правила запихнуты в контроллер, типа проверки остатков и лимита заказа:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductRepository productRepository;
@PostMapping
public ResponseEntity<?> createOrder(@RequestBody CreateOrderRequest request) {
// Validation logic
if (request.getProductId() == null || request.getQuantity() <= 0) {
return ResponseEntity
.badRequest()
.body("Invalid request");
}
// Business logic
Product product = productRepository.findById(request.getProductId())
.orElse(null);
if (product == null) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body("Product not found");
}
if (product.getStock() < request.getQuantity()) {
return ResponseEntity
.badRequest()
.body("Not enough stock");
}
BigDecimal totalPrice = product.getPrice()
.multiply(BigDecimal.valueOf(request.getQuantity()));
if (totalPrice.compareTo(new BigDecimal("10000")) > 0) {
return ResponseEntity
.badRequest()
.body("Order limit exceeded");
}
// Persistence + transaction logic
product.setStock(product.getStock() - request.getQuantity());
productRepository.save(product);
Order order = new Order();
order.setProduct(product);
order.setQuantity(request.getQuantity());
order.setTotalPrice(totalPrice);
order.setCreatedAt(LocalDateTime.now());
orderRepository.save(order);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(order.getId());
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Как снизить хвостовые задержки в Java с помощью ZGC: читать
Он заметно снижает хвостовые задержки (p999/p9999) по сравнению с G1 за счет микропауз, но платит за это повышенным CPU и при нехватке процессора может упираться в allocation stalls, поэтому включать его стоит только после замеров на своей нагрузке.
👉 Java Portal
Он заметно снижает хвостовые задержки (p999/p9999) по сравнению с G1 за счет микропауз, но платит за это повышенным CPU и при нехватке процессора может упираться в allocation stalls, поэтому включать его стоит только после замеров на своей нагрузке.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Rate limiting в системном дизайне: один пользователь или сервис не должен слишком часто дергать API и завалить его.
В Spring Boot для этого можно использовать библиотеку Bucket4j и сделать Rate Limit Filter.
Она умеет:
▪️ защищать от примитивных DDoS-атак
▪️ отсеивать кривых клиентов, которые шлют запросы в цикле
▪️ ограничивать число запросов за единицу времени
▪️ делать доступ чуть более честным: понемногу всем, а не все одному
Очень просто, быстро и потокобезопасно.
▪️ На каждый запрос проверяет, есть ли в кэше ключ клиента (например IP). Если нет, создает для него bucket с токенами.
▪️ Каждый раз пытается забрать из bucket один токен, то есть право выполнить запрос.
▪️ Если токен в bucket есть, проходишь. Если токены закончились, получаешь HTTP 429 и ждешь пополнения.
Заметки:
-> request.getRemoteAddr() ищет корректный способ получить IP клиента, возможно через request.getHeader("X-Forwarded-For")
-> new ConcurrentHashMap<>() сам по себе не чистится, продумай, как долго хранить данные и как их вычищать, если запросов много
-> лимит задается одинаковый для всех эндпоинтов. Часто у разных API разная нагрузка, поэтому логично ставить разные лимиты (по URL, HTTP-методу или типу операции)
-> refillGreedy() это всего лишь один из вариантов пополнения токенов. Есть и другие стратегии (плавное пополнение, фиксированные интервалы), которые дают более точный контроль нагрузки
-> вынеси все настройки в application.yaml, чтобы менять лимиты без правок кода
Простая реализация, чтобы понять, как работает библиотека, приложена
👉 Java Portal
В Spring Boot для этого можно использовать библиотеку Bucket4j и сделать Rate Limit Filter.
Она умеет:
Очень просто, быстро и потокобезопасно.
Заметки:
-> request.getRemoteAddr() ищет корректный способ получить IP клиента, возможно через request.getHeader("X-Forwarded-For")
-> new ConcurrentHashMap<>() сам по себе не чистится, продумай, как долго хранить данные и как их вычищать, если запросов много
-> лимит задается одинаковый для всех эндпоинтов. Часто у разных API разная нагрузка, поэтому логично ставить разные лимиты (по URL, HTTP-методу или типу операции)
-> refillGreedy() это всего лишь один из вариантов пополнения токенов. Есть и другие стратегии (плавное пополнение, фиксированные интервалы), которые дают более точный контроль нагрузки
-> вынеси все настройки в application.yaml, чтобы менять лимиты без правок кода
Простая реализация, чтобы понять, как работает библиотека, приложена
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Совет для IntelliJ: Alt+Enter можно использовать, чтобы быстро чинить ошибки и предупреждения, но список вариантов там довольно ограничен.
Вместо этого используй автодополнение команд (..), чтобы выполнять нужные действия прямо в редакторе.
👉 Java Portal
Вместо этого используй автодополнение команд (..), чтобы выполнять нужные действия прямо в редакторе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤3🔥2
Spring Boot: не используй
✗ Помечая связь как
✗ В этом примере каждый раз, когда ты загружаешь
✗ И ещё: если не делать явный fetch, получаешь классический эффект N+1:
1. Один запрос на все
2. По одному запросу на каждый
👉 Java Portal
FetchType.EAGER, если реально нет необходимости.✗ Помечая связь как
EAGER, ты говоришь ORM подгружать её каждый раз вместе с сущностью, даже если ты вообще не обращаешься к этой связи (не вызываешь геттер/метод отношения).✗ В этом примере каждый раз, когда ты загружаешь
Order, ORM автоматически подтянет и Customer:@Entity
class Order {
@ManyToOne(fetch = FetchType.EAGER)
private Customer customer;
}
✗ И ещё: если не делать явный fetch, получаешь классический эффект N+1:
1. Один запрос на все
Orders2. По одному запросу на каждый
Order для CustomersPlease open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2
HTTP/2 через TCP против HTTP/3 через QUIC
▪️ HTTP/2
▪️ HTTP/3
👉 Java Portal
Мультиплексирование на уровне HTTP, сериализация на уровне TCP
Общий порядок доставки и контроль перегрузки (TCP)
Одна TCP-сессия
HTTP/2 фреймы (мультиплексированные)
* HEADERS (поток 1)
* HEADERS (поток 3)
* HEADERS (поток 2)
* DATA (поток 1)
* DATA (поток 3)
* DATA (поток 2)
TCP-пакеты: P1, P2, P3, P4, P5
TCP-пакеты смешивают данные из разных потоков
HoL-блокировка в TCP (Head-of-Line): потеря одного пакета блокирует все потоки
Клиент -> Сервер
Мультиплексирование на транспортном уровне (QUIC)
* Независимые потоки
* Независимый порядок доставки и восстановление
QUIC-соединение (поверх UDP)
QUIC Stream 1: QUIC Packet, QUIC Packet, QUIC Packet
QUIC Stream 2: QUIC Packet, QUIC Packet
QUIC Stream 3: QUIC Packet, QUIC Packet
Нет HoL-блокировки: потеря пакета влияет только на один поток
Клиент -> Сервер
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Java tip: для точных расчетов времени используй Duration и Instant.
✅ Instant представляет конкретный момент времени в UTC с точностью до наносекунд. Получить можно так:
✅ Duration показывает временной интервал между двумя
Вот пример:
👉 Java Portal
Instant.now(). Instant (в секундах, миллисекундах, наносекундах). Вот пример:
Instant start = Instant.now();
...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8