Java Portal | Программирование
12.8K subscribers
1.23K photos
104 videos
38 files
1.19K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Аннотации Spring Boot, которые нужно знать

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
18🔥5
Java-совет: начиная с Java 11, лучше использовать String.strip() вместо trim(), потому что он корректно обрабатывает Unicode-пробелы.

Поскольку trim() не обрабатывает некоторые типы пробельных символов, определённых в Unicode, он может оставлять неожиданные символы.

String.strip() использует Character.isWhitespace(int codePoint) для определения пробелов. Этот метод следует полному стандарту Unicode для пробельных символов, а не только ASCII, и удаляет все виды пробелов.

Пример:

String text = "\u2003Hello World\u2003";
System.out.println("trim(): [" + text.trim() + "]");
System.out.println("strip(): [" + text.strip() + "]");


Смысл сохранён полностью: trim() ограничен ASCII, strip() работает по Unicode-правилам и ведёт себя ожидаемо.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Недавно открыл для себя learn.java — официальный сайт от Oracle для изучения Java. Здесь всё чётко и по делу 😈

> Установка JDK и настройка IDE
> Пошаговые уроки по основам Java
> Практические задания в онлайн-редакторе
> Мини-проекты для закрепления знаний
> Дополнительные ресурсы для углубленного обучения

Плюс — есть Java Playground, где можно писать и запускать код прямо в браузере, без лишних установок

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥114
Spring Boot: аккуратно задавайте границы @ComponentScan, чтобы случайно не сканировать целые пакеты целиком.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83
This media is not supported in your browser
VIEW IN TELEGRAM
Следуешь DDD и подходу model-first в Spring Data JDBC? Писать миграции Flyway или Liquibase руками и держать в голове синтаксис каждой конкретной БД — утомительно и легко накосячить.

IntelliJ IDEA позволяет генерировать миграции напрямую из ваших сущностей.

Подробнее: https://jb.gg/b8o1hq

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Java-совет: используй WeakHashMap для кэширования в случаях, когда ключи мапы без внешних ссылок должны автоматически удаляться сборщиком мусора.

В HashMap, пока сама мапа существует, ключи и связанные с ними значения не будут удалены сборщиком мусора.

В WeakHashMap ключи хранятся через weak-ссылки. Если на ключ больше нет strong-ссылок в других местах программы, GC может его собрать, и он будет автоматически удалён из мапы.

Пример:

Map<User, String> map = new WeakHashMap<>();

User u1 = new User("Mick");
map.put(u1, "Cached data");
...
u1 = null;

// С этого момента ключ u1 может быть удалён сборщиком мусора.


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍64
java programs.pdf
124.3 KB
От базовых до продвинутых программ на Java

39 программ на Java, каждая из которых решает отдельную задачу, включая разворот строки, проверку на палиндром, генерацию чисел Фибоначчи, вычисление факториала, проверку простого числа, сортировку массива, удаление дубликатов, поиск наибольшего элемента, и многое другое

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot: для отправки писем можно использовать spring-boot-starter-mail.

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

Добавь зависимость:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>


Настрой почтовые параметры в application.properties (или application.yml):

spring.mail.host=smtp.gmail.com
spring.mail.port=587
[email protected]
spring.mail.password=my_password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true


Используй JavaMailSender в коде:

@Autowired
private JavaMailSender mailSender;

public void sendEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
message.setFrom("[email protected]");

mailSender.send(message);
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
CodingBat Java: это сайт с интерактивными задачами по Java

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
6🤔1
бэкенд-разработчики после написания 4 строк CSS.

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

Значение создаётся лениво (только при первом обращении).

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍1
Тонкие Docker-образы для Java: в этой статье вы узнаете, как собирать тонкие Docker-образы для ваших Java-приложений с использованием Alpine Linux и инструмента jlink.

Мы будем опираться на свежие базовые образы Java 21 от Eclipse Temurin и BellSoft Liberica. Также мы сравним этих провайдеров с Alpaquita Linux, который тоже поставляется BellSoft. В сравнение также войдет оценка безопасности на основе количества уязвимостей. В качестве примера мы возьмем простое Spring Boot-приложение, которое поднимает несколько REST-эндпоинтов.

Если вам интересна Java в контексте контейнеризации, на моем блоге вы можете найти несколько похожих статей. Например, можно почитать, как ускорить старт Java на Kubernetes с помощью CRaC в том посте. Еще есть статья, где сравниваются разные провайдеры JDK, которые используются для запуска Java-приложений в Paketo Buildpacks.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Совет: в REST-сервисах ты часто получаешь только ID сущностей. И не всегда нужно тащить их из БД.

Чтобы проставить связь (по сути, foreign key в базе), можно “создать” ссылку на сущность через getReferenceById(id) без SELECT и использовать её, чтобы задать relation.

@Service
public SomeService {

@Autowired
private ProductRepository productRepository;

@Autowired
private CategoryRepository featureRepository;

public void setCategory(long productId, long categoryId) {
Product product = productRepository.findById(productId).orElseThrow(); // executes SELECT
Category category = categoryRepository.getReferenceById(categoryId); // does not execute a SELECT
product.setCategory(category);
productRepository.save(product);
}

}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍5
Spring Boot: можно реализовать оптимистическую блокировку через аннотацию @Version.

Идеально подходит, когда:

- чтения происходят часто
- записи сравнительно редкие
- конфликты случаются нечасто

Не лучший вариант, когда:

- конфликты происходят часто
- нужна строгая сериализация

public class Account {

@Id
private Long id;

private BigDecimal balance;

@Version
private Long version;
}


Когда читаем, Entity загружается с текущей версией. Допустим, version = 2.

Когда делаем update, учитывается запись с version = 2.

Если за это время другая транзакция уже успела её обновить, version уже не 2, апдейт не затронет ни одной строки, и Hibernate кинет OptimisticLockException.

То есть конфликт ловится без блокировки строки.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Реальный event-driven проект на Core Java 21, Apache Kafka (KRaft mode) и PostgreSQL (в Docker).

Проект показывает, как современные распределенные системы обрабатывают заказы асинхронно через Kafka, без блокировок и ожидания между сервисами.

https://github.com/FlexiDriod/kafka-order-processing-system

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣2😁1
Spring Boot: отдавай предпочтение статическим utility-классам вместо Spring-бинов только если они не хранят состояние, у них нет зависимостей и их не нужно мокать или оборачивать в AOP.

public class CacheUtils {
private static Map<String, String> cache = new HashMap<>();

...
}

// Кэш как выше разделяется между всеми потоками и может случайно изменяться

@Component
@Scope("request")
public class CacheService {
private Map<String, String> cache = new HashMap<>();

...
}

// Если оформить это как бин, можно задать ему конкретный scope.

// Spring лучше управляет объектами с состоянием.


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👀3💊31
Большинство разработчиков в Spring знают, как доставать query-параметры и path variables.

Но часто забывают, что HTTP-хедеры можно вытаскивать так же просто. В Spring для этого есть аккуратный @RequestHeader.

Можно в одну строку получить User-Agent, Authorization или любой кастомный хедер. И не нужно лезть в HttpServletRequest.

Пример:

▪️Добавляешь в метод контроллера @RequestHeader("User-Agent") String userAgent
▪️Spring сам подхватывает значение из заголовка
▪️Ты получаешь его сразу параметром метода

Нужно сделать опциональным?
Просто добавь required = false.

Нужен дефолт?

▪️Используй defaultValue = "unknown".
▪️Очень полезно для логирования, аналитики, A/B тестов или фичефлагов, завязанных на заголовки.
▪️Выручает при работе с API-клиентами, которые шлют кастомные заголовки.
▪️Чище, короче и легче тестируется.
▪️Чем меньше зависимостей от servlet API, тем лучше.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20
...Script


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁114
Java-совет: чтобы не ловить оверхед на boxing/unboxing, используй стримы примитивов (IntStream/LongStream/DoubleStream) вместо Stream<Integer>/Stream<Long>/Stream<Double>.

Создаём объекты Integer для каждого значения:

Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sumBoxed = boxed.reduce(0, Integer::sum);


Работаем напрямую с int:

int sumPrimitive = IntStream.of(1, 2, 3, 4, 5).sum();


Другие примитивные стримы:

LongStream, DoubleStream

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3
Как прогревать кэши в Spring Boot?

И вообще, как делать что-то на старте приложения?

Обычно такие операции делают в @PostConstruct или ловят событие ApplicationReadyEvent. Но у этих вариантов есть заметный минус.

Если “прогрев” лежит в @PostConstruct, как его отключать в тестах? Можно завести флаг, сделать наследника и подменять бин в тестовой конфигурации, но это не всегда помогает и часто выглядит как костыль.

Покажу более элегантный способ “прогрева кэшей”. В какой-то момент точно пригодится.

Смотри: SpringApplication.run(...) возвращает полностью готовый контекст. Из него можно получить нужный компонент и вызвать метод “прогрева”. Код выглядит так:

@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MainApplication.class, args);
AccountService accService = ctx.getBean(AccountService.class);
accService.loadDictionary();
}
}


В чём плюс?

В интеграционных тестах с @SpringBootTest метод main не запускается. Значит, код внутри не выполняется. Никаких костылей вокруг @PostConstruct, всё чисто и аккуратно.

Когда всё-таки нужно, чтобы “прогрев” выполнялся и в тестах, добавь параметр “использовать main метод”:

@SpringBootTest(useMainMethod = SpringBootTest.UseMainMethod.ALWAYS)


И всё. Если код должен выполняться после старта, но мешает тестам, клади его в main. Очень полезный приём.

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