Java Ready | Программирование
8.95K subscribers
1.37K photos
75 videos
1 file
718 links
Авторский канал по разработке на Java.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Автор: @energy_c

Реклама на бирже: https://telega.in/c/java_ready
Download Telegram
Делаем простой rate limiter на Java!

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

В этой задаче:
• храним timestamps действий;
• удаляем устаревшие записи;
• проверяем размер окна;


Такой вариант хорошо подходит для понимания идеи sliding window и небольших локальных сценариев.

👉 Java Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4🔥2
Делаем простой TTL-кэш на Java!

Иногда значение нужно хранить не навсегда, а только короткое время: ответ API, результат вычисления или временную настройку.

Опишем запись кэша:
record Entry<T>(T value, long expiresAt) {}


Создадим хранилище:
Map<String, Entry<String>> cache = new HashMap<>();


Добавим значение с временем жизни:
void put(String key, String value, long ttlMs) {
cache.put(key, new Entry<>(
value,
System.currentTimeMillis() + ttlMs
));
}


Теперь достанем значение:
String get(String key) {
var entry = cache.get(key);

if (entry == null) {
return null;
}

if (entry.expiresAt() < System.currentTimeMillis()) {
cache.remove(key);
return null;
}

return entry.value();
}


Проверка:
put("token", "abc", 1000);

System.out.println(get("token"));


Ожидаемый вывод:
abc


После истечения TTL метод вернёт null, а устаревшая запись удалится из Map.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍5🔥4👎1
Шпаргалка по Maven!

Например, mvn test запускает тесты, mvn package собирает артефакт, а mvn dependency:tree показывает дерево зависимостей проекта.
На картинке основные Maven-команды, фазы lifecycle, полезные параметры командной строки, локальный репозиторий, Maven Central и популярные плагины: help, dependency, compiler, version, wrapper, Spring Boot и exec.

Сохрани, чтобы не потерять!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍7🔥6
Разбираем Sequenced Collections!

В Java 21 появился общий API для коллекций, у которых есть понятный порядок элементов: первый, последний и обратный обход. Раньше для этого приходилось помнить разные методы у List, Deque, LinkedHashMap и других структур.

👉 Java Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍65
Статья про E2EE-мессенджер на Spring Boot и WebCrypto!

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

В статье автор показывает:
• как устроена сессия и обмен ключами
• зачем нужен ratchet-подход для сообщений
• какие архитектурные ошибки легко допустить при E2EE

Продолжай читать на Habr!


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥4👍2🤝2
Делаем простой HTTP-запрос через HttpClient!

Иногда нужно без сторонних библиотек сходить в API, получить JSON или проверить доступность. Начиная с Java 11 для этого есть встроенный HttpClient.

Сначала создадим клиент:
HttpClient client = HttpClient.newHttpClient();


Теперь соберём request:
HttpRequest request = HttpRequest.newBuilder()


Укажем адрес:
.uri(URI.create("https://api.github.com"))


Выберем GET-запрос:
.GET()


И соберём объект:
.build();


Ответ можно получить синхронно:
var response = client.send(request,
HttpResponse.BodyHandlers.ofString());


Код статуса лежит отдельно:
System.out.println(response.statusCode());


Тело ответа можно прочитать так:
System.out.println(response.body());


Для реального кода почти всегда стоит добавить timeout. Тогда запрос не сможет зависнуть навсегда:
.timeout(Duration.ofSeconds(5))


Если запросов много, клиент лучше переиспользовать. Он потокобезопасный и нормально подходит для сервисов, CLI-утилит и фоновых задач.

Такой подход удобен, когда нужно быстро сделать интеграцию без OkHttp, Apache HttpClient и других зависимостей.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍114🔥4
Почему ThreadLocal нужно чистить после использования?

ThreadLocal удобен, когда значение должно быть привязано к конкретному потоку:
private static final ThreadLocal<String> USER_ID =
new ThreadLocal<>();


Например, в начале обработки запроса можно сохранить id пользователя:
USER_ID.set("user-42");


А ниже по коду достать его без передачи через каждый метод:
String userId = USER_ID.get();


Но в серверных приложениях потоки часто переиспользуются пулом.

Если значение не удалить, следующий запрос может попасть на тот же поток и увидеть старые данные.

Поэтому после работы важно очищать ThreadLocal:
try {
USER_ID.set(userId);
handleRequest();
} finally {
USER_ID.remove();
}


finally нужен, чтобы очистка сработала даже при исключении.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍2🔥2🤝2
Собираем сортировку задач по зависимостям!

Нужно получить порядок выполнения задач, где одна задача может зависеть от другой. Например, сначала build, потом test, а deploy только после test.

В этой задаче:
• описываем граф зависимостей
• считаем входящие связи
• кладём свободные задачи в очередь


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

👉 Java Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1🔥1
Почему Collections.unmodifiableList не делает настоящую копию?

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

Для этого часто используют Collections.unmodifiableList.
List<String> roles = new ArrayList<>();
List<String> view = Collections.unmodifiableList(roles);


Через view действительно нельзя вызвать add или remove. Такой вызов закончится исключением.

Но важный нюанс в том, что unmodifiableList создаёт не копию, а представление поверх исходного списка.

Если изменить оригинальный список, изменения будут видны и через view.
roles.add("admin");
System.out.println(view);


На экране появится новое значение, хотя сам view вроде бы неизменяемый. Он просто запрещает менять список через себя, но не защищает от изменений оригинала.

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

Если нужна именно независимая копия, лучше использовать List.copyOf.
List<String> snapshot = List.copyOf(roles);


Теперь snapshot не связан с дальнейшими изменениями исходного списка. Это уже снимок состояния на момент создания.

Разница особенно заметна в классах с внутренним состоянием.
class User {
private final List<String> roles = new ArrayList<>();

List<String> roles() {
return List.copyOf(roles);
}
}


Так вызывающий код получает безопасный результат и не может случайно повлиять на объект изнутри.

Если элементы списка сами изменяемые, копия списка не делает глубокую копию элементов. Например, список объектов UserRole всё ещё будет содержать те же самые объекты.

Поэтому для настоящей неизменяемости важно думать не только о коллекции, но и о типах внутри неё. Для строк, чисел, enum и record-объектов такой подход обычно работает хорошо.

Плохой вариант выглядит так.
class User {
private final List<String> roles;

User(List<String> roles) {
this.roles = roles;
}
}


Если внешний код сохранит ссылку на исходный список, он сможет поменять состояние объекта уже после создания.

Безопаснее делать defensive copy прямо в конструкторе.
this.roles = List.copyOf(roles);


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

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥6👍4
Шпаргалка по устройству JVM!

Например, Heap хранит объекты и делится на young/old generation, а Stack содержит фреймы вызовов, локальные переменные и работает отдельно для каждого потока.

На картинке основные области памяти JVM: Heap, Stack, Metaspace, PC Register и Native Method Stack, а также краткая логика работы GC и сравнение популярных сборщиков мусора.

Сохрани, чтобы не потерять!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍64🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Очнись, нас готовят к цифровому ГУЛАГу

Уже в десятках регионов России отключают мобильный интернет (даже когда нет атак БПЛА), тестируют «белые списки» и замедляют Телегу.

90% людей тупо смотрят на уплывающий корабль свободного Интернета. Люди поумнее готовятся к новой реальности и читают «Пакет Безопасности».

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

Без шуток, сейчас это один из самых полезных каналов в Телеге. Надеемся на лучшее, но к чему нужно готовиться — вы и сами понимаете: @package_security
👎6