Java Portal | Программирование
12.9K subscribers
1.22K photos
103 videos
37 files
1.16K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Spring Boot: используй CommandLineRunner, чтобы выполнять логику при старте приложения.

CommandLineRunner это интерфейс Spring Boot. Его можно реализовать, чтобы запускать код после того, как контекст приложения полностью инициализирован.

Некоторые сценарии, где это уместно:

Заполнение БД начальными данными
Запуск health-check’ов при старте
Бутстрап внешних сервисов/ресурсов

Пример:

@Component
public class StartupRunner implements CommandLineRunner {

@Override
public void run(String... args) {
System.out.println("Приложение запущено! Дальнейшая настройка");
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Please open Telegram to view this post
VIEW IN TELEGRAM
34🔥11👍4🤣2🏆1
Spring Boot: чтобы при сериализации в Jackson исключать любые поля, у которых значение null, можно использовать аннотацию @JsonInclude(Include.NON_NULL)

@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserDTO {

private Long id;
private String name;
private String email;
private String phone;

...
}


Все пустые поля исключаются автоматически.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73🤔2
Шпаргалка по разрядам чисел, максимальным и минимальным значениям

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53
Spring Boot: на этапе разработки используй spring.main.lazy-initialization=true, чтобы ускорить старт приложения.

По умолчанию Spring Boot жадно инициализирует все бины на старте. В дев-окружении это значит:

1. Дольше стартует, особенно в больших проектах
2. Приходится ждать загрузки бинов, которые тебе прямо сейчас не нужны

Чтобы этого избежать, в application.properties поставь:

spring.main.lazy-initialization=true


Но в проде важно оставить дефолтное поведение, потому что:

1. Ошибки старта ловятся раньше
2. Все компоненты сразу готовы принимать запросы

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
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 и не мутируя его

// 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();


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
10 золотых правил чистого кода:

1. Избегай магических чисел и строк
2. Используй осмысленные, говорящие имена
3. Предпочитай ранние return вместо глубокой вложенности
4. Избегай длинных списков параметров
5. Делай функции маленькими и сфокусированными
6. Соблюдай DRY (Don’t Repeat Yourself) — не дублируй код
7. Применяй принцип KISS (Keep It Simple, Stupid) — делай проще
8. Отдавай предпочтение композиции, а не наследованию
9. Комментируй только там, где это действительно необходимо
10. Пиши хорошие сообщения к коммитам

Какие еще правила чистого кода ты бы добавил в этот список?

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥6
Совет по Java: если нужна максимально хорошая производительность в общем случае, бери HashMap как реализацию Map.

HashMap внутри реализован как хеш-таблица, и в среднем put(), get() и remove() работают за O(1).

🪲Он не потокобезопасный (если нужна thread-safety, используй 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());
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94💊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
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥4
Java-совет: начиная с 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";
};


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍177
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
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥3
Spring Boot: лучше не использовать wildcard-исключения для транзитивных зависимостей в POM-файлах, потому что они могут прятать проблемы.

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>


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3
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-часть.

Плохой пример: бизнес-правила запихнуты в контроллер, типа проверки остатков и лимита заказа:

@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());
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Как снизить хвостовые задержки в Java с помощью ZGC: читать

Он заметно снижает хвостовые задержки (p999/p9999) по сравнению с G1 за счет микропауз, но платит за это повышенным CPU и при нехватке процессора может упираться в allocation stalls, поэтому включать его стоит только после замеров на своей нагрузке.

👉 Java Portal
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
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
👍73🔥2
Spring Boot: не используй FetchType.EAGER, если реально нет необходимости.

✗ Помечая связь как EAGER, ты говоришь ORM подгружать её каждый раз вместе с сущностью, даже если ты вообще не обращаешься к этой связи (не вызываешь геттер/метод отношения).

✗ В этом примере каждый раз, когда ты загружаешь Order, ORM автоматически подтянет и Customer:

@Entity
class Order {
@ManyToOne(fetch = FetchType.EAGER)
private Customer customer;
}


✗ И ещё: если не делать явный fetch, получаешь классический эффект N+1:

1. Один запрос на все Orders
2. По одному запросу на каждый Order для Customers

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