Библиотека Java разработчика
10.8K subscribers
1.14K photos
564 videos
58 files
1.44K links
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP
Download Telegram
Когда нужно использовать raw types?

Сначала вспомним, что такое raw type. В Java так называют generic-типы без указания типа-параметра. Такая языковая конструкция валидна, но в большинстве случаев приводит к предупреждению компилятора.

Предупреждение связано с риском получения проблемы heap pollution. Ей мы уже посвящали публикации ранее. Использование raw types никогда не оправдано – спецификация языка явно говорит: их поддержка остается только для обратной совместимости.

Есть всего три случая, когда использовать обобщенный тип без параметра правильно:
• Целевая версия Java < 5.0 (2002 год и ранее – вряд ли это ваш случай);
• В литерале класса. List<String>.class не сработает, нужно писать List.class;
• В операторе instanceof. Вместо instanceof Set<Integer> должно быть instanceof Set.

👉@BookJava
👍2
🚀AutoCloseable HTTP Client в Java 21

👉@BookJava
👍4
Beyond Loom: Weaving new concurrency patterns

В этой статье мы обсудим некоторые новые паттерны для параллельных систем, которые стали возможны благодаря новой функции виртуальных потоков в Java 21, а также некоторые связанные с ней функции, которые "следуют" за виртуальными потоками - в частности, Structured Concurrency (JEP 453) и Scoped Values (JEP 446).

Обратите внимание, что в JDK 21 структурированный параллелизм и скопированные значения находятся в состоянии Preview и поэтому не могут быть использованы в продакшен-приложениях.

Учитывая это ограничение, давайте начнем с рассмотрения паттернов, которые поддерживаются только виртуальными потоками и, следовательно, могут без ограничений использоваться в приложениях Java 21.

https://developers.redhat.com/articles/2023/10/03/beyond-loom-weaving-new-concurrency-patterns#

👉@BookJava
👍5👏1
Совет по использованию Java API 💡

Использование Java Stream flatMap 🔥

👉@BookJava
👍9
🚀 Советы по Spring Boot 💡

Библиотека Spring Boot Startup Report генерирует интерактивный отчет о запуске приложения Spring Boot, который позволяет понять, что влияет на время запуска приложения, и, возможно, поможет его оптимизировать. 🔥

https://github.com/maciejwalkowiak/spring-boot-startup-report

👉@BookJava
👍8🔥6
Как вызвать транзакционный метод из того же класса?

В Spring Framework существует аннотация @Transactional. Ей помечается метод или класс, весь код которого должен выполняться в рамках транзакции. Обычно имеется в виду транзакция базы данных, но вообще это понятие определяется используемым transactionManager-ом. Настройки, такие как уровень изоляции, стратегия роллбэка и прочие, определяются через параметры этой аннотации.

В теории, @Transactional делает метод транзакционным для этого класса и всех его наследников. На практике же, по умолчанию, если вызвать транзакционный метод Foo.bar() из Foo.baz(), то транзакция не создастся.

Это происходит вследствие того, что по умолчанию Spring AOP добавляет код открытия/закрытия транзакции через динамический proxy класс. То есть, вместо Foo инджектится нечто, похожее на код на изображении.

Первый вариант решения проблемы – вместо аннотации использовать TransactionTemplate, то есть обернуть код в транзакцию вручную. Примеры использования можно посмотреть в этой статье.

Другой, более универсальный, но более сложный в конфигурации способ – переключить режим работы Spring AOP с динамических прокси на нечто другое. Обычно применяется библиотека AspectJ:

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)


В Spring AOP есть понятие weaving – этап добавления дополнительной функциональности (аспектов). В нашем случае, это код открытия/закрытия транзакции. Чтобы заработал weaving AspectJ этапа компиляции, в сборку нужно добавить плагин: aspectj-maven-plugin для maven, gradle-aspectj для gradle.

Подробнее об экспериментах с разными режимами Spring AOP можно почитать в статье на хабре.

👉@BookJava
👍4
Двухфакторная аутентификация с помощью Spring Security

В этой статье мы рассмотрим двухфакторную аутентификацию с помощью Spring Security. Мы будем использовать soft token с Spring Security.

Добавление дополнительного уровня безопасности для вашего приложения всегда является хорошей практикой, особенно с учетом меняющейся динамики безопасности. Для некоторых приложений наличие двухфакторной аутентификации является обязательным требованием. Хотя в Spring security нет встроенной двухфакторной аутентификации, но гибкая архитектура Spring Security Architecture позволяет легко добавить эту функциональность в ваше приложение.

https://www.javadevjournal.com/spring-security/two-factor-authentication-with-spring-security/

👉@BookJava
👍5
Шпаргалка по структурам данных в Java

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

https://habr.com/ru/articles/751648/

👉@BookJava
👍3🥰2
Советы по Spring 💡

Создайте отказоустойчивый микросервис с помощью паттерна Circuit Breaker, используя Resilience4j. 🔥

https://resilience4j.readme.io/

👉@BookJava
👍8
Совет по Java ☕️

В Java 22 появился новый форматированный тип `ListFormat`. Он создает или разбирает список конкатенированных строк с учетом локальных особенностей. Предусмотрено 3 типа конкатенации: STANDARD, OR и UNIT, и 3 стиля для каждого типа: FULL, SHORT и NARROW.

👉@BookJava
🔥7👍2👀1
Media is too big
VIEW IN TELEGRAM
Java. Префиксное дерево. Основные операции, сохранение в файл, практическое применение.

В данном видео я рассказываю о префиксных деревьях. Разбираем, что из себя представляет префиксное дерево, для чего оно применяется. Изучаем и реализуем основные операции с префиксным деревом на языке программирования Java. Кроме этого я показываю как сохранить дерево в файл и потом загрузить обратно. С помощью этого проверяю, насколько выгодней может быть хранение строк в префиксном дереве на примере автомобильных номеров.

00:00 - Вступление
00:26 - Применение в приложении
01:58 - Построение дерева и операции с ним
06:33 - Построение префиксного дерева на Java
11:22 - Операции с префиксным деревом на Java
16:31 - Сохранение дерева в файл
20:51 - Загрузка дерева из файла
25:32 - Экономия по сравнению со списком
27:12 - Замечание о Null-безопасности
28:26 - Заключение

источник

👉@BookJava
👍5
Советы по Spring 💡

Чтобы выполнять действия в транзакции базы данных, вы можете использовать шаблон Spring TransactionTemplate вместо @Transactional

👉@BookJava
👍8
В отличие от других немодульных "soft keywords" в Java (permits, sealed, yield, record, var), здесь разрешено использовать "when" в качестве имени типа, так что этот код совершенно допустим. Интересно, было ли это сознательное исключение, или на него не обратили внимания...

👉@BookJava
👍3🤮1
♨️ Прокачивай свои навыки вместе с Java | Фишки и трюки

Ежедневные порции Java-фишек, полезные советы и трюки от опытных разработчиков.

👉🏼 Присоединиться
👍5🔥1
Обновленный Java Roadmap 2024📌

https://github.com/devoxx/JavaRoadmap

👉@BookJava
👍5🤡2
Как сгенерировать хорошее случайное число?

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

Псевдослучайные числа – это последовательность случайных на вид чисел, на самом деле полученных в результате математического алгоритма. Последовательность таких чисел можно воспроизвести, зная начальные условия (seed, энтропия) и используемый алгоритм. Метод, который используется для генерации чисел в классе java.util.Random, дает криптографически ненадежные псевдослучайные числа – злоумышленник может достаточно легко их предугадывать.

Истинно случайные числа основываются на физических свойствах, которые трудно поддаются измерению. Это могут быть, например, доли секунд текущего системного времени. Алгоритм генерации истинно случайных чисел не позволяет с хорошей точностью угадать следующее число, даже зная предыдущие.

Класс SecureRandom предоставляет доступ к криптографически надежным генераторам случайных чисел. При том, это могут быть как достаточно сложные последовательности псевдослучайных, так и истинно случайные числа. Согласно стандартам безопасности, они будут достаточно непредсказуемы.

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

Внутри SecureRandom использует SPI. Мы можем выбирать из различных алгоритмов генерации и их провайдеров, указав их названия в фабричном методе getInstance. Все перечисленные выше свойства определяются именно используемым алгоритмом.

👉@BookJava
👍8😁1👀1
Media is too big
VIEW IN TELEGRAM
Совет по Spring

В этом выпуске мы рассмотрим новый проект Spring Boot Testjars, который значительно упрощает создание и повторное использование сателлитных Java-сервисов, таких как микросервисы на базе Spring Boot или инфраструктура, например, Spring Authorization Server.

👉@BookJava
👍4
MyBatis «на минималках»

В этой статье расскажу про не очень распространённый фреймворк MyBatis.

Почему MyBatis? Потому что мы в CDEK используем его в большинстве проектов, и в деле он весьма неплохо себя показал. Немного сложен и непривычен на этапе входа, но все эти минусы перекрываются его гибкостью. «Да есть Hibernate, Jooq, JDBC и еще что‑то», — скажут бывалые. Есть, но в данной статье речь пойдёт о MyBatis.

Статья будет полезна новичкам, которые хотели попробовать данный фреймворк или попробовали, но что‑то не получилось.

https://habr.com/ru/companies/cdek_blog/articles/771714/

👉@BookJava
👍3
В чем различие между приватным конструктором и финальным классом?

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

Если добавить объявлению класса модификатор final, это также запретит от него наследоваться, уже без излишнего ограничения на использование конструктора снаружи. Это основное применение этих двух подходов.

С точки зрения возможности наследования, ограничение через private конструктор более слабое. От такого класса, если он не финальный, можно наследовать внутренние и вложенные подклассы. Публичный вложенный класс может сработать как «паблик морозов» – дать внешним классам наследоваться через себя.

class NonInheritable {
private NonInheritable() {}

public static class PublicMorozov extends NonInheritable {}
}

class SubClass extends NonInheritable. PublicMorozov {
//
Технически, это наследник NonInheritable. Никакой ошибки!

👉@BookJava
👍61