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

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
бэкенд-разработчики после написания 4 строк CSS.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁32🌚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👍6
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
👍3
Реальный 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
👍22
...Script


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁154
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
4👍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
5
Spring Boot: можно использовать @Retryable, чтобы переживать нестабильность внешних сервисов.

@Service
public class ExtService {

@Retryable(
value = { HttpServerErrorException.class, ResourceAccessException.class },
maxAttempts = 3,
backoff = @Backoff(delay = 2000, multiplier = 2)
)
public ExtServiceResponse process(ExtServiceRequest request) {
// Call external payment gateway
return restTemplate.postForObject("https://ext-gateway/api/service", request,
ExtServiceResponse.class);
}

@Recover
public ExtServiceResponse recover(Exception e, ExtServiceRequest request) {
// Fallback logic after retries are exhausted
log.error("Failed after retries: {}", e.getMessage());
return new ExtServiceResponse("FAILED");
}
}


Что это делает:

▪️Делает 3 ретрая, если вылетают указанные исключения.
▪️Стартует с задержки 2 секунды и удваивает ее на каждой попытке (экспоненциальный backoff).
▪️Если все попытки провалились, вызывает recover().

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1
Вопрос для собеседования по Spring Boot:

Какой будет результат запуска, если активный профиль не указан?

Spring по умолчанию выберет бин DevNotificationService
Spring выберет первый бин в алфавитном порядке
Приложение упадет с NoSuchBeanDefinitionException
Бины не будут созданы, но приложение запустится
Будут созданы оба бина - NoUniqueBeanDefinitionException

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Java tip : старайся не шарить данные между потоками.

Используй иммутабельные объекты
Либо пусть потоки общаются через сообщения, не трогая общий state напрямую и не мутируя shared-состояние

// С иммутабельными объектами:

record Book(String title, int price) {} // Иммутабельный

public class BookJob implements Runnable {
private final Book book;
.... // конструктор

@Override
public void run() {
System.out.println(book.title() + " " + book.price());
}
}

// Обмен сообщениями:

...
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
1🌚1
Какой SQL-запрос будет выполнен при вызове метода findByEmail()?

1. SELECT * FROM users WHERE email LIKE ?

2. SELECT id, name, email FROM users WHERE email LIKE ?

3. SELECT * FROM users WHERE email = ? LIMIT 1

4. SELECT * FROM users WHERE email = ?

5. SELECT * FROM users WHERE email = email

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot: используй @SpringBootApplication(exclude = …), чтобы отключить конкретные классы автоконфигурации.

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

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
java.evolved это подборка, где каждый старый паттерн из Java показан рядом с его современным заменителем, прямо бок о бок.

👍👍👍

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥2
Совет по Spring Boot: если тебе нужны интеграционные тесты для контроллеров Spring MVC, а всё остальное ты хочешь замокать, используй @WebMvcTest — он поднимет только MVC-бины (контроллеры, конфиг MVC, конвертеры, валидацию и т.п.), без полного контекста приложения.

▪️Он грузит только MVC-бины, а не весь application context целиком.

▪️Интеграционные тесты медленнее юнитов, поэтому их стоит ускорять, выкидывая все лишнее, что не нужно конкретно для MVC.

▪️В этом примере мы мокaем бин HelloService и поднимаем только MVC-контекст и сам контроллер:

@WebMvcTest(HelloController.class)
class HelloControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private HelloService helloService; // замокано

@Test
void sayHello_returnsExpectedMessage() throws Exception {
given(helloService.getMessage()).willReturn("Hello!");
mockMvc.perform(get("/api/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello!"));
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Пожизненная PRO-подписка на easyoffer по цене одного года.

Беспрецедентная акция на PRO-тариф сайта для подготовки к собеседованию на программиста, тестировщика, проектного менеджера и другие IT-профессии.

⚙️ Доступные функции сейчас:
1. База вопросов из реальных технических собеседований с вероятностью встречи и примерами ответов.
2. База задач с этапа live-coding.
3. База 1100+ реальных собеседований, в том числе в топовые компании (Сбер, Авито, Яндекс, WB, OZON, МТС и др.) на позиции Junior/Middle/Senior.
4. База 400+ тестовых заданий от компаний.
5. Аналитика ТОП-требований из вакансий для лучшего написания резюме по ключевым словам.
6. Тренажеры для подготовки к собеседованию. В том числе тренажер «Реальное собеседование» со сценарием вопросов под конкретную компанию.

⌛️ Функции, которые появятся в ближайшие полгода:
1. Агрегатор вакансий из Telegram, сайтов компаний и джоббордов.
2. Улучшение и оптимизация резюме, чтобы проходить ATS-системы.
3. Генерация уникального резюме и сопроводительного письма под вакансию.

Акция до 20 февраля (включительно) на PRO-тариф. Покупаешь сейчас один раз — пользуешься всю жизнь без лимита, включая все будущие функции.

👉 Смотри подробности тарифа и покупай на easyoffer
🤣5💊1
Spring Boot: Используй ResponseEntity<T>, чтобы получить тонкий контроль над HTTP-ответом.

Можно явно задать status, headers и body.

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