🚀 Протестируйте приложение с помощью Taikai
Taikai - это мощное расширение популярной библиотеки
https://github.com/enofex/taikai
👉@BookJava
Taikai - это мощное расширение популярной библиотеки
ArchUnit
, предлагающее полный набор предопределенных правил, адаптированных для различных технологий. 🔥https://github.com/enofex/taikai
👉@BookJava
👍7😱2
Где у Java приложения точка входа?
В обычном Java приложении всегда должен быть
main обязательно
В главном методе должен быть объявлен единственный аргумент – массив строк. Обе конструкции
Когда приложение запускается как
Для исполняемого jar-файла (java -jar MyJar.jar), его главный класс должен быть указан в манифесте. Внутри архива, в файл
В случае, когда в указанном главном классе не оказывается метода, который бы удовлетворял всем критериям главного метода, программа падает с ошибкой «Main method not found».
В апплетах вместо main входной точкой служат методы
👉@BookJava
В обычном Java приложении всегда должен быть
main class
, содержащий метод main
. С него начинается исполнение всей программы. Main class
-ом может быть не только класс, но и интерфейс или енам. Для JavaFX приложения главный класс должен реализовывать javafx.application.Application
.main обязательно
public static
. Дополнительно, методу разрешено иметь модификатор strictfp. На аннотации и список исключений ограничений не накладывается.В главном методе должен быть объявлен единственный аргумент – массив строк. Обе конструкции
String[]
и String
... компилируются в один и тот же байт-код, так что приемлемы оба варианта. Название массива может быть любым, а значение будет содержать аргументы командной строки.Когда приложение запускается как
classpath
, главный класс передается параметром командной строки. Если выполняется единственный исходник, он и описывает main class
.Для исполняемого jar-файла (java -jar MyJar.jar), его главный класс должен быть указан в манифесте. Внутри архива, в файл
META-INF/MANIFEST.MF
добавляется строчка вида Main-Class: ru.google.com.MyClass
. Иначе запуск завершается ошибкой «no main manifest attribute
».В случае, когда в указанном главном классе не оказывается метода, который бы удовлетворял всем критериям главного метода, программа падает с ошибкой «Main method not found».
В апплетах вместо main входной точкой служат методы
init
и start
. Начиная с версии Java 9 технология апплетов объявлена устаревшей, а с 11 – совсем удалена. Не будем останавливаться на них подробнее.👉@BookJava
👍6❤1
Hibernate и спецификация JPA: приключение на 20 минут
На прошлой неделе в блоге сообщества Spring АйО вышла статья-перевод про интересный кейс падения производительности при переходе на Hibernate 6.5. Оказалось, что выражения вида publisherId in :ids при пустом ids приводит к серьезной деградации производительности. Баг вскоре был пофикшен, однако, не дает покоя вопрос, почему так произошло?
Ниже приводим историю появления и незамедлительного решения этой проблемы, от лица Гэвина Кинга, создателя Hibernate.
https://habr.com/ru/companies/spring_aio/articles/821307/
👉@BookJava
На прошлой неделе в блоге сообщества Spring АйО вышла статья-перевод про интересный кейс падения производительности при переходе на Hibernate 6.5. Оказалось, что выражения вида publisherId in :ids при пустом ids приводит к серьезной деградации производительности. Баг вскоре был пофикшен, однако, не дает покоя вопрос, почему так произошло?
Ниже приводим историю появления и незамедлительного решения этой проблемы, от лица Гэвина Кинга, создателя Hibernate.
https://habr.com/ru/companies/spring_aio/articles/821307/
👉@BookJava
👍1
🚀 Простой сервис HTTP-запросов и ответов 🚀
Очень хорошо подходит для тестирования ваших http-запросов! 🔥
https://httpbin.org/#/Response_inspection
👉@BookJava
Очень хорошо подходит для тестирования ваших http-запросов! 🔥
https://httpbin.org/#/Response_inspection
👉@BookJava
👍4👏1
Что такое «лямбда»? Какова структура и особенности использования лямбда-выражения?
Лямбда представляет собой набор инструкций, которые можно выделить в отдельную переменную и затем многократно вызвать в различных местах программы.
Основу лямбда-выражения составляет лямбда-оператор, который представляет стрелку ->. Этот оператор разделяет лямбда-выражение на две части: левая часть содержит список параметров выражения, а правая собственно представляет тело лямбда-выражения, где выполняются все действия.
Лямбда-выражение не выполняется само по себе, а образует реализацию метода, определенного в функциональном интерфейсе. При этом важно, что функциональный интерфейс должен содержать только один единственный метод без реализации.
По факту лямбда-выражения являются в некотором роде сокращенной формой внутренних анонимных классов, которые ранее применялись в Java.
Отложенное выполнение (deferred execution) лямбда-выражения- определяется один раз в одном месте программы, вызываются при необходимости, любое количество раз и в произвольном месте программы.
Параметры лямбда-выражения должны соответствовать по типу параметрам метода функционального интерфейса:
Конечные лямбда-выражения не обязаны возвращать какое-либо значение.
Блочные лямбда-выражения обрамляются фигурными скобками. В блочных лямбда-выражениях можно использовать внутренние вложенные блоки, циклы, конструкции if, switch, создавать переменные и т.д. Если блочное лямбда-выражение должно возвращать значение, то явным образом применяется оператор return:
Передача лямбда-выражения в качестве параметра метода:
👉@BookJava
Лямбда представляет собой набор инструкций, которые можно выделить в отдельную переменную и затем многократно вызвать в различных местах программы.
Основу лямбда-выражения составляет лямбда-оператор, который представляет стрелку ->. Этот оператор разделяет лямбда-выражение на две части: левая часть содержит список параметров выражения, а правая собственно представляет тело лямбда-выражения, где выполняются все действия.
Лямбда-выражение не выполняется само по себе, а образует реализацию метода, определенного в функциональном интерфейсе. При этом важно, что функциональный интерфейс должен содержать только один единственный метод без реализации.
interface Operationable {
int calculate(int x, int y);
}
public static void main(String[] args) {
Operationable operation = (x, y) -> x + y;
int result = operation.calculate(10, 20);
System.out.println(result); //30
}
По факту лямбда-выражения являются в некотором роде сокращенной формой внутренних анонимных классов, которые ранее применялись в Java.
Отложенное выполнение (deferred execution) лямбда-выражения- определяется один раз в одном месте программы, вызываются при необходимости, любое количество раз и в произвольном месте программы.
Параметры лямбда-выражения должны соответствовать по типу параметрам метода функционального интерфейса:
operation = (int x, int y) -> x + y;
//При написании самого лямбда-выражения тип параметров разрешается не указывать:
(x, y) -> x + y;
//Если метод не принимает никаких параметров, то пишутся пустые скобки, например:
() -> 30 + 20;
//Если метод принимает только один параметр, то скобки можно опустить:
n -> n * n;
Конечные лямбда-выражения не обязаны возвращать какое-либо значение.
interface Printable {
void print(String s);
}
public static void main(String[] args) {
Printable printer = s -> System.out.println(s);
printer.print("Hello, world");
}
Блочные лямбда-выражения обрамляются фигурными скобками. В блочных лямбда-выражениях можно использовать внутренние вложенные блоки, циклы, конструкции if, switch, создавать переменные и т.д. Если блочное лямбда-выражение должно возвращать значение, то явным образом применяется оператор return:
Operationable operation = (int x, int y) -> {
if (y == 0) {
return 0;
}
else {
return x / y;
}
};
Передача лямбда-выражения в качестве параметра метода:
interface Condition {
boolean isAppropriate(int n);
}
private static int sum(int[] numbers, Condition condition) {
int result = 0;
for (int i : numbers) {
if (condition.isAppropriate(i)) {
result += i;
}
}
return result;
}
public static void main(String[] args) {
System.out.println(sum(new int[] {0, 1, 0, 3, 0, 5, 0, 7, 0, 9}, (n) -> n != 0));
}
👉@BookJava
👍9👏1
К каким переменным есть доступ у лямбда-выражений?
Доступ к переменным внешней области действия из лямбда-выражения очень схож к доступу из анонимных объектов. Можно ссылаться на:
⚫️ неизменяемые (effectively final - не обязательно помеченные как
⚫️ поля класса;
⚫️ статические переменные.
К методам по умолчанию реализуемого функционального интерфейса обращаться внутри лямбда-выражения запрещено.
Как отсортировать список строк с помощью лямбда-выражения?
👉@BookJava
Доступ к переменным внешней области действия из лямбда-выражения очень схож к доступу из анонимных объектов. Можно ссылаться на:
final
) локальные переменные;К методам по умолчанию реализуемого функционального интерфейса обращаться внутри лямбда-выражения запрещено.
Как отсортировать список строк с помощью лямбда-выражения?
public static List<String> sort(List<String> list){
Collections.sort(list, (a, b) -> a.compareTo(b));
return list;
}
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Что такое «ссылка на метод»?
Если существующий в классе метод уже делает все, что необходимо, то можно воспользоваться механизмом method reference (ссылка на метод) для непосредственной передачи этого метода. Такая ссылка передается в виде:
⚫️ имя_класса::имя_статического_метода для статического метода;
⚫️ объект_класса::имя_метода для метода экземпляра;
⚫️ название_класса::new для конструктора.
Результат будет в точности таким же, как в случае определения лямбда-выражения, которое вызывает этот метод.
Ссылки на методы потенциально более эффективны, чем использование лямбда-выражений. Кроме того, они предоставляют компилятору более качественную информацию о типе и при возможности выбора между использованием ссылки на существующий метод и использованием лямбда-выражения, следует всегда предпочитать использование ссылки на метод.
👉@BookJava
Если существующий в классе метод уже делает все, что необходимо, то можно воспользоваться механизмом method reference (ссылка на метод) для непосредственной передачи этого метода. Такая ссылка передается в виде:
Результат будет в точности таким же, как в случае определения лямбда-выражения, которое вызывает этот метод.
private interface Measurable {
public int length(String string);
}
public static void main(String[] args) {
Measurable a = String::length;
System.out.println(a.length("abc"));
}
Ссылки на методы потенциально более эффективны, чем использование лямбда-выражений. Кроме того, они предоставляют компилятору более качественную информацию о типе и при возможности выбора между использованием ссылки на существующий метод и использованием лямбда-выражения, следует всегда предпочитать использование ссылки на метод.
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Как применяют технологию SPI
Service Provider Interface – технология из стандартной поставки JavaSE. Этой технологией реализуется IoC, не являющаяся при этом DI. С помощью SPI можно легко и без дополнительных инструментов поставлять конкретные реализации сервисов отдельными jar-файлами. Применение обычно похоже на механизм плагинов.
Два основных понятия SPI – это service и service provider. Service – интерфейс или абстрактный класс, который объявляет API требуемого сервиса, и предоставляется основным приложением. Service provider – реализация этого API, наследник класса/интерфейса сервиса, который динамически поставляется в основное приложение библиотекой-плагином. Для одного сервиса может быть предоставлено несколько провайдеров из одной или нескольких библиотек.
На интерфейс сервиса не накладывается никаких ограничений. Провайдер же обязан реализовывать этот интерфейс, и иметь конструктор без параметров. Внутри jar-файла в директории META-INF/services лежат текстовые файлы, где имя файла – полное имя сервиса, а его строчки – полные имена провайдеров этого сервиса, которые поставляются этой библиотекой.
Для получения провайдеров всех библиотек приложения используется класс ServiceLoader. Это итератор по сервис-провайдерам, а создается он статическим методом load, в который параметром передается интерфейс/абстрактный класс интересующего сервиса.
Доступ к файлам-ресурсам из classpath обеспечивается загрузчиком классов, поэтому дополнительно при загрузке можно указать специфический загрузчик. С появлением модульности в Java 9 можно также указать модуль.
SPI повсеместно используется в стандартной библиотеке JDK. С его помощью подключаются JDBC-драйверы. Через ServiceLoader также загружаются таймзоны, системные настройки, кодировки, провайдеры файловой системы и многое другое.
👉@BookJava
Service Provider Interface – технология из стандартной поставки JavaSE. Этой технологией реализуется IoC, не являющаяся при этом DI. С помощью SPI можно легко и без дополнительных инструментов поставлять конкретные реализации сервисов отдельными jar-файлами. Применение обычно похоже на механизм плагинов.
Два основных понятия SPI – это service и service provider. Service – интерфейс или абстрактный класс, который объявляет API требуемого сервиса, и предоставляется основным приложением. Service provider – реализация этого API, наследник класса/интерфейса сервиса, который динамически поставляется в основное приложение библиотекой-плагином. Для одного сервиса может быть предоставлено несколько провайдеров из одной или нескольких библиотек.
На интерфейс сервиса не накладывается никаких ограничений. Провайдер же обязан реализовывать этот интерфейс, и иметь конструктор без параметров. Внутри jar-файла в директории META-INF/services лежат текстовые файлы, где имя файла – полное имя сервиса, а его строчки – полные имена провайдеров этого сервиса, которые поставляются этой библиотекой.
Для получения провайдеров всех библиотек приложения используется класс ServiceLoader. Это итератор по сервис-провайдерам, а создается он статическим методом load, в который параметром передается интерфейс/абстрактный класс интересующего сервиса.
Доступ к файлам-ресурсам из classpath обеспечивается загрузчиком классов, поэтому дополнительно при загрузке можно указать специфический загрузчик. С появлением модульности в Java 9 можно также указать модуль.
SPI повсеместно используется в стандартной библиотеке JDK. С его помощью подключаются JDBC-драйверы. Через ServiceLoader также загружаются таймзоны, системные настройки, кодировки, провайдеры файловой системы и многое другое.
👉@BookJava
👍7
Что такое «функциональные интерфейсы»?
Функциональный интерфейс - это интерфейс, который определяет только один абстрактный метод.
Чтобы точно определить интерфейс как функциональный, добавлена аннотация
Интерфейс может включать сколько угодно default методов и при этом оставаться функциональным, потому что default методы - не абстрактные.
👉@BookJava
Функциональный интерфейс - это интерфейс, который определяет только один абстрактный метод.
Чтобы точно определить интерфейс как функциональный, добавлена аннотация
@FunctionalInterface
, работающая по принципу @Override
. Она обозначит замысел и не даст определить второй абстрактный метод в интерфейсе.Интерфейс может включать сколько угодно default методов и при этом оставаться функциональным, потому что default методы - не абстрактные.
👉@BookJava
👍5
Для чего нужны функциональные интерфейсы Function<T,R>, DoubleFunction<R>, IntFunction<R> и LongFunction<R>?
Function<T, R> - интерфейс, с помощью которого реализуется функция, получающая на вход экземпляр класса
Методы по умолчанию могут использоваться для построения цепочек вызовов (
⚫️ DoubleFunction<R> - функция получающая на вход Double и возвращающая на выходе экземпляр класса R;
⚫️ IntFunction<R> - функция получающая на вход Integer и возвращающая на выходе экземпляр класса R;
⚫️ LongFunction<R> - функция получающая на вход Long и возвращающая на выходе экземпляр класса R.
👉@BookJava
Function<T, R> - интерфейс, с помощью которого реализуется функция, получающая на вход экземпляр класса
T
и возвращающая на выходе экземпляр класса R
.Методы по умолчанию могут использоваться для построения цепочек вызовов (
compose
, andThen
).Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
backToString.apply("123"); // "123"
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Что делает семафор?
Семафор – один из старейших примитивов синхронизации. Он был изобретен Дейкстрой в 1968 году. По большому счету это счетчик, который можно увеличивать и уменьшать из разных потоков. Уменьшение до 0 блокирует уменьшающий поток. Состояние, когда счетчик больше нуля называют сигнальное состояние, операцию его увеличения – release (освобождение) или signal, уменьшения – acquire (захват) или wait.
На практике можно представить, что release – выделение квоты доступа к критической секции программы. acquire – использование необходимого объема доступной квоты, или ожидание, если её не хватает.
В Java семафор реализован классом Semaphore. Состоит этот класс в основном из разных форм методов acquire (с таймаутом, с игнорированием InterruptedException, неблокирующий) и release. Методы могут принимать параметр permits – тот самый объем квот, которые необходимо освободить/захватить.
Несколько вспомогательных методов позволяют узнать больше о количестве и составе очереди потоков, которые ждут освобождения пермитов. А методы availablePermits и drainPermits позволяют узнать количество оставшихся пермитов, и захватить их все соответственно. В конструкторе конфигурируются изначальное количество пермитов, и свойство fair (аналогичное свойству ReentrantLock).
👉@BookJava
Семафор – один из старейших примитивов синхронизации. Он был изобретен Дейкстрой в 1968 году. По большому счету это счетчик, который можно увеличивать и уменьшать из разных потоков. Уменьшение до 0 блокирует уменьшающий поток. Состояние, когда счетчик больше нуля называют сигнальное состояние, операцию его увеличения – release (освобождение) или signal, уменьшения – acquire (захват) или wait.
На практике можно представить, что release – выделение квоты доступа к критической секции программы. acquire – использование необходимого объема доступной квоты, или ожидание, если её не хватает.
В Java семафор реализован классом Semaphore. Состоит этот класс в основном из разных форм методов acquire (с таймаутом, с игнорированием InterruptedException, неблокирующий) и release. Методы могут принимать параметр permits – тот самый объем квот, которые необходимо освободить/захватить.
Несколько вспомогательных методов позволяют узнать больше о количестве и составе очереди потоков, которые ждут освобождения пермитов. А методы availablePermits и drainPermits позволяют узнать количество оставшихся пермитов, и захватить их все соответственно. В конструкторе конфигурируются изначальное количество пермитов, и свойство fair (аналогичное свойству ReentrantLock).
👉@BookJava
👍5
Media is too big
VIEW IN TELEGRAM
Обновление Java с 17 на 21: через тернии к звездам
Меня зовут Денис, я тимлид команды R&D в Naumen Service Management Platform.
Как большие почитатели языка Java, мы, Naumen Service Management Platform, стараемся мигрировать на свежие версии языка. Причин множество: это и улучшенная безопасность, и появление крутых языковых фич, и буст перформанса. Но путь не всегда оказывается простым.
В докладе я расскажу, с какими проблемами и препятствиями мы столкнулись при обновлении продукта Naumen SMP на новую LTS версию Java. Также поделюсь мыслями, а зачем вообще стоит обновляться.
Доклад будет полезен разработчикам и техлидам, которые задумываются или уже планируют миграцию их систем на Java 21.
https://habr.com/ru/companies/naumen/articles/822639/
👉@BookJava
Меня зовут Денис, я тимлид команды R&D в Naumen Service Management Platform.
Как большие почитатели языка Java, мы, Naumen Service Management Platform, стараемся мигрировать на свежие версии языка. Причин множество: это и улучшенная безопасность, и появление крутых языковых фич, и буст перформанса. Но путь не всегда оказывается простым.
В докладе я расскажу, с какими проблемами и препятствиями мы столкнулись при обновлении продукта Naumen SMP на новую LTS версию Java. Также поделюсь мыслями, а зачем вообще стоит обновляться.
Доклад будет полезен разработчикам и техлидам, которые задумываются или уже планируют миграцию их систем на Java 21.
https://habr.com/ru/companies/naumen/articles/822639/
👉@BookJava
👍3👎1🤔1
Для чего нужны функциональные интерфейсы UnaryOperator<T>, DoubleUnaryOperator, IntUnaryOperator и LongUnaryOperator?
UnaryOperator<T> (унарный оператор) принимает в качестве параметра объект типа T, выполняет над ними операции и возвращает результат операций в виде объекта типа T:
⚫️ DoubleUnaryOperator - унарный оператор получающий на вход Double;
⚫️ IntUnaryOperator - унарный оператор получающий на вход Integer;
⚫️ LongUnaryOperator - унарный оператор получающий на вход Long.
👉@BookJava
UnaryOperator<T> (унарный оператор) принимает в качестве параметра объект типа T, выполняет над ними операции и возвращает результат операций в виде объекта типа T:
UnaryOperator<Integer> operator = x -> x * x;
System.out.println(operator.apply(5)); // 25
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Как Spring Framework реализует паттерн Dependency Injection?
Инверсия контроля (inversion of control, IoC) – принцип проектирования, по которому контроль над потоком управления передается фреймворку. Управляющий и прикладной код разделяются. При разработке модуля этот подход избавляет от необходимости знать о других модулях программы и деталях их взаимодействия. Такой код становится более переипользуемым и модульным, уменьшает связность.
Внедрение зависимостей (Dependency Injection, DI) – одна из реализаций IoC. При взаимодействии с другими модулями, программа оперирует высокоуровневыми абстракциями, тогда как конкретная её реализация поставляется фреймворком.
Стандартная реализация DI – фреймворк инстанциирует все сервисы, и складывает их в IoC-контейнер. При этом специальная сущность, Service Locator, занимается поиском соответствия реализаций абстракциям и их внедрением.
Spring – большой набор различных библиотек. DI реализуется одной из основных библиотек – Spring IoC.
Сущности бизнес-логики в Spring, как и в JavaEE называются beans. Бины объявляются различными способами, корни большинства из них лежат в понятии Configuration. В качестве контейнера бинов выступает ApplicationContext. Чтобы передать инициализацию зависимости контексту, она помечается аннотацией
👉@BookJava
Инверсия контроля (inversion of control, IoC) – принцип проектирования, по которому контроль над потоком управления передается фреймворку. Управляющий и прикладной код разделяются. При разработке модуля этот подход избавляет от необходимости знать о других модулях программы и деталях их взаимодействия. Такой код становится более переипользуемым и модульным, уменьшает связность.
Внедрение зависимостей (Dependency Injection, DI) – одна из реализаций IoC. При взаимодействии с другими модулями, программа оперирует высокоуровневыми абстракциями, тогда как конкретная её реализация поставляется фреймворком.
Стандартная реализация DI – фреймворк инстанциирует все сервисы, и складывает их в IoC-контейнер. При этом специальная сущность, Service Locator, занимается поиском соответствия реализаций абстракциям и их внедрением.
Spring – большой набор различных библиотек. DI реализуется одной из основных библиотек – Spring IoC.
Сущности бизнес-логики в Spring, как и в JavaEE называются beans. Бины объявляются различными способами, корни большинства из них лежат в понятии Configuration. В качестве контейнера бинов выступает ApplicationContext. Чтобы передать инициализацию зависимости контексту, она помечается аннотацией
@Autowired
.👉@BookJava
🔥4❤1👍1
Реализация авторизации на основе ролей в Spring Boot с помощью Keycloak
Контроль доступа на основе ролей является обязательным условием для любого приложения, имеющего дело с пользователями, которые могут получать доступ к определенным ресурсам в зависимости от своей роли в организации.
В предыдущей статье мы узнали, как защитить Spring Boot REST API с помощью Keycloak, используя протокол аутентификации OpenID Connect.
В этой статье мы добавим авторизацию на основе ролей.
Цель состоит в том, чтобы разрешить доступ к некоторым конечным точкам только пользователям с определенной ролью. Точнее, мы собираемся ограничить доступ к конечной точке DELETE и сделать его доступным только пользователям с ролью администратора.
https://gauthier-cassany.com/posts/spring-boot-keycloak-roles
👉@BookJava
Контроль доступа на основе ролей является обязательным условием для любого приложения, имеющего дело с пользователями, которые могут получать доступ к определенным ресурсам в зависимости от своей роли в организации.
В предыдущей статье мы узнали, как защитить Spring Boot REST API с помощью Keycloak, используя протокол аутентификации OpenID Connect.
В этой статье мы добавим авторизацию на основе ролей.
Цель состоит в том, чтобы разрешить доступ к некоторым конечным точкам только пользователям с определенной ролью. Точнее, мы собираемся ограничить доступ к конечной точке DELETE и сделать его доступным только пользователям с ролью администратора.
https://gauthier-cassany.com/posts/spring-boot-keycloak-roles
👉@BookJava
👍5
Spring Boot 3.2: замените свой RestTemplate на RestClient
В мире Spring Boot отправка HTTP запросов к внешним сервисам является весьма распространенной задачей. Традиционно при достижении этой цели разработчики полагались на RestTemplate. Однако, по мере развития Spring Framework, на свет появился новый и более мощный способ обработки HTTP запросов: так называемый WebClient. Spring Boot 3.2 представил нам новый API для REST запросов: RestClient, использующий те же принципы fluent api, что и WebClient.
RestClient предлагает нам более современные и интуитивно понятные способы взаимодействия с RESTful сервисами.
https://habr.com/ru/companies/spring_aio/articles/822529/
👉@BookJava
В мире Spring Boot отправка HTTP запросов к внешним сервисам является весьма распространенной задачей. Традиционно при достижении этой цели разработчики полагались на RestTemplate. Однако, по мере развития Spring Framework, на свет появился новый и более мощный способ обработки HTTP запросов: так называемый WebClient. Spring Boot 3.2 представил нам новый API для REST запросов: RestClient, использующий те же принципы fluent api, что и WebClient.
RestClient предлагает нам более современные и интуитивно понятные способы взаимодействия с RESTful сервисами.
https://habr.com/ru/companies/spring_aio/articles/822529/
👉@BookJava
👍3❤1
Что такое StringJoiner?
⚫️
⚫️
⚫️
👉@BookJava
ObjDoubleConsumer<T>
- операция, которая принимает два аргумента классов T
и Double
, производит с ними некоторое действие и ничего не возвращает;ObjLongConsumer<T>
- операция, которая принимает два аргумента классов T
и Long
, производит с ними некоторое действие и ничего не возвращает;ObjIntConsumer<T>
- операция, которая принимает два аргумента классов T
и Integer
, производит с ними некоторое действие и ничего не возвращает.👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Совет по Spring Boot💡
Когда вам нужно настроить bean, предоставляемый Spring Boot, проверьте наличие интерфейсов *
👉@BookJava
Когда вам нужно настроить bean, предоставляемый Spring Boot, проверьте наличие интерфейсов *
Customizer
- велика вероятность, что вы сможете настроить bean
, не отказываясь от автоконфигурации.👉@BookJava
👍12
Совет по Spring Boot💡
После аннотации bean с
👉@BookJava
После аннотации bean с
@Validated
, вы можете использовать параметры метода валидации с аннотациями валидации bean
, такими как @NotNull
, @NotBlank
и т.д.👉@BookJava
👍5❤4
Чем отличается ReentrantLock от обычного Lock?
Примеры не-reentrant локов из стандартной библиотеки – представления класса StampedLock, возвращаемые его методами
👉@BookJava
Lock
– это интерфейс, ReentrantLock
– его реализация. «Reentrant» говорит о том, что один и тот же поток может перезахватывать уже захваченный лок. Интерфейс не требует этого свойства. Обычный блок synchronized
тоже является reentrant
– вложенная синхронизация на том же мониторе отработает без проблем.Примеры не-reentrant локов из стандартной библиотеки – представления класса StampedLock, возвращаемые его методами
asReadLock()
и asWriteLock()
.👉@BookJava
👍6