Шаг 3: JWT Authentication Filter
Шаг 4: Security Configuration
Шаг 5: Application Configuration
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
final String jwt = authHeader.substring(7);
final String username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
Шаг 4: Security Configuration
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Шаг 5: Application Configuration
@Configuration
@RequiredArgsConstructor
public class ApplicationConfig {
private final UserRepository userRepository;
@Bean
public UserDetailsService userDetailsService() {
return username -> userRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config)
throws Exception {
return config.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
👍5❤4🔥2
Шаг 6: Auth Controller
Шаг 7: application.yml
Важно: генерируйте JWT_SECRET через Jwts.SIG.HS512.key().build() и храните в переменных окружения!
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthenticationManager authenticationManager;
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@PostMapping("/login")
public ResponseEntity<AuthResponse> login(@RequestBody AuthRequest request) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.email(),
request.password()
)
);
UserDetails user = userDetailsService.loadUserByUsername(request.email());
String token = jwtService.generateToken(user);
return ResponseEntity.ok(new AuthResponse(token));
}
}
Шаг 7: application.yml
jwt:
secret: ${JWT_SECRET}
expiration: 86400000 # 24 hours
spring:
security:
filter:
dispatcher-types: REQUEST, ERROR, ASYNC
Важно: генерируйте JWT_SECRET через Jwts.SIG.HS512.key().build() и храните в переменных окружения!
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤5🔥3🥱1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
readOnly = true — это
Что происходит:
—
—
—
Важно: это
#spring
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2❤1👏1
🔥 Топ-10 интересных ошибок в реальных проектах
PVS-Studio собрали подборку самых интересных багов 2025 года из крупных Open Source проектов.
Тут есть всё: неочевидные языковые нюансы, которые ломают логику, ошибки из-за особенностей инициализации, проблемы с типами там, где их не ждёшь. Каждая ошибка разобрана с примерами кода и объяснением, почему она возникла.
Особенно понравится тем, кто любит копаться в деталях языка и понимать, как на самом деле работает JVM под капотом.
🔗 Читать на Habr
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
PVS-Studio собрали подборку самых интересных багов 2025 года из крупных Open Source проектов.
Тут есть всё: неочевидные языковые нюансы, которые ломают логику, ошибки из-за особенностей инициализации, проблемы с типами там, где их не ждёшь. Каждая ошибка разобрана с примерами кода и объяснением, почему она возникла.
Особенно понравится тем, кто любит копаться в деталях языка и понимать, как на самом деле работает JVM под капотом.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5👍2🔥1
Наш подписчик спрашивает:
Вопрос к сообществу. Начальство загорелось идеей прикрутить к проекту AI. Проект на Spring Boot 3, Java 21. Юзал кто Spring AI? Подводные камни, баги, альтернативы?
Фреймворк на первый взгляд удобный, но я наткнулся на статью, где разраб жалуется, что между версиями меняются даже названия пакетов. Код с октября уже не работает. Примеры в интернете все разные в зависимости от даты написания.
P.S. Если хотите задать вопрос, заполните нашу гугл-форму. Это займет 5 минут.
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8👍1🔥1
Java-разработчик — от 250 000 ₽ — офис (Екатеринбург)
Java-developer Middle/Middle+ — удалёнка
Java разработчик (senior) — удалёнка
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28💯4👍2
В статье рассмотрены 3 подхода к построению API. Также автор показывает, как объединить gRPC и GraphQL, чтобы фронт получал гибкие запросы, а бэк получал скорость и эффективность.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2❤1👏1
Forwarded from Библиотека задач по Java | тесты, код, задания
Что будет результатом кода?
Anonymous Quiz
14%
NPE
59%
a
6%
null
16%
Ошибка компиляции
5%
Посмотреть ответ
👍8🔥2
Когда проект разрастается до десятков микросервисов, появляется ряд вопросов, которые не возникают, если у тебя монолит:
— Как сервису А узнать, где сейчас живёт сервис Б (тем более, если адреса постоянно меняются)?
— Как не утонуть в километрах кода для HTTP-запросов?
— Как фронтенду работать с этой кучей сервисов?
Для этого есть три главных инструмента.
В облаке сервисы постоянно перезапускаются, меняют IP-адреса и порты. Хардкодить http://localhost:8082 не вариант.
Eureka Server работает как справочная служба
🔹 При старте каждый сервис стучится в Eureka: «Я на связи, вот мой адрес».
🔹 Когда сервису А нужно достучаться до Б, он обращается к Eureka: «Подскажи, где сейчас сервис Б».
Нужно добавить аннотацию
@EnableDiscoveryClient для работы Eureka. Сервисы будут находить друг друга по имени, а не по IP.Для отправки запросов между сервисами можно использовать RestTemplate. Но код получается довольно громоздким и не типизированным.
Вместо этого можно использовать Feign. Он позволяет вызывать удаленный REST-сервис так, будто это обычный метод интерфейса. А вся реализация генерируется под капотом.
@FeignClient(name = "account-service") // Имя сервиса в Eureka
public interface AccountClient {
@GetMapping("/account/{userId}")
List<Account> getAccount(@PathVariable Long userId);
}
// Использование в сервисе:
List<Account> accounts = accountClient.getAccount(13L);
Теперь следующая проблема: сервисы между собой нормально общаются, а вот фронт всё ещё не знает кому точно отправлять запрос. Можно сложить на фронт адреса каждого сервиса, но это сложно и небезопасно.
Тут на помощь и приходит Spring Cloud Gateway. Он выступает как КПП. Фронт стучится только в него, а он уже сам разруливает запрос к нужным сервисам.
Например: запросы на /users/** идут в UserService.
🔹 Что он делает
— Маршрутизация: смотрит на путь запроса и решает, в какой именно сервис его отправить.
— Безопасность: проверяет JWT токен один раз на входе.
— Rate Limiting: защита от спама (например, максимум 10 запросов в секунду с одного IP).
1. Сервисы стартуют и сообщают Eureka о себе.
2. Фронт отправляет запрос в Gateway.
3. Gateway узнаёт у Eureka, где живёт нужный сервис, и перенаправляет запрос.
4. Когда сервисам нужно поговорить друг с другом, в дело вступает Feign.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥3❤1👏1
Мультиагентные системы: взгляд изнутри
В мире Java есть LangChain4j, но основные инновации обкатываются на Python. Курс «Разработка ИИ-агентов» — это отличный способ понять архитектурные паттерны построения LLM-приложений.
Что изучаем (на Python):
— жизненный цикл агента и
— оркестрацию через графы (
— интеграцию с корпоративными данными (RAG).
Знание этих паттернов позволит вам эффективно проектировать AI-сервисы и на Java. Для курса нужен базовый Python.
Смотреть первую лекцию
Записаться
В мире Java есть LangChain4j, но основные инновации обкатываются на Python. Курс «Разработка ИИ-агентов» — это отличный способ понять архитектурные паттерны построения LLM-приложений.
Что изучаем (на Python):
— жизненный цикл агента и
ReAct;— оркестрацию через графы (
LangGraph);— интеграцию с корпоративными данными (RAG).
Знание этих паттернов позволит вам эффективно проектировать AI-сервисы и на Java. Для курса нужен базовый Python.
Смотреть первую лекцию
Записаться
🔧 Jackson: безопасная десериализация в Spring Boot
Дефолтные настройки Jackson молча игнорируют неизвестные поля в JSON и используют небезопасные типы. В production это маскирует ошибки контрактов API и открывает векторы атак через полиморфную десериализацию.
🔹 Решение
▪️ Настройка через application.yml
▪️ Программная настройка
▪️ Для критичных DTO добавьте валидацию
📊 Результат:
— Ошибки контракта API детектируются сразу
— Защита от JSON injection атак
— Консистентный формат дат
— Меньше трафика (no nulls)
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Дефолтные настройки Jackson молча игнорируют неизвестные поля в JSON и используют небезопасные типы. В production это маскирует ошибки контрактов API и открывает векторы атак через полиморфную десериализацию.
🔹 Решение
▪️ Настройка через application.yml
spring:
jackson:
deserialization:
fail-on-unknown-properties: true # фейлим на лишние поля
fail-on-null-for-primitives: true
serialization:
write-dates-as-timestamps: false # ISO-8601 вместо timestamp
fail-on-empty-beans: false
default-property-inclusion: non_null # не сериализуем null
mapper:
default-view-inclusion: true
▪️ Программная настройка
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// Безопасность
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.activateDefaultTyping(
BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(Object.class)
.build(),
ObjectMapper.DefaultTyping.NON_FINAL
);
// Даты
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// Null handling
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return mapper;
}
}
▪️ Для критичных DTO добавьте валидацию
@JsonIgnoreProperties(ignoreUnknown = false) // строго
public record UserDto(
@NotNull String username,
@JsonProperty("email_address") String email,
@JsonFormat(pattern = "yyyy-MM-dd") LocalDate birthDate
) {}
📊 Результат:
— Ошибки контракта API детектируются сразу
— Защита от JSON injection атак
— Консистентный формат дат
— Меньше трафика (no nulls)
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2🔥1👏1🤔1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁23👍2❤1🔥1💯1
Java в Enterprise + AI Agents = Мощный стек
Крупный бизнес 2026 года активно внедряет AI, и ему нужны надёжные решения. Как встроить LLM-агента в экосистему Spring? Как обеспечить безопасность данных?
На курсе мы учим архитектурному подходу. Мы разбираем паттерны построения агентов, которые можно реализовать на любом языке (в том числе через Spring AI), или интегрировать Python-микросервисы в вашу Java-инфраструктуру. Реальные кейсы, разбор ошибок и фокус на Enterprise.
Ключевые темы:
— Паттерны надёжности (Retry, Fallback, Circuit Breaker) при работе с LLM.
— Интеграция с корпоративными Knowledge Base (RAG).
— Безопасность и контроль доступа (RBAC) в агентных системах.
Освоить проектирование AI-систем
Крупный бизнес 2026 года активно внедряет AI, и ему нужны надёжные решения. Как встроить LLM-агента в экосистему Spring? Как обеспечить безопасность данных?
На курсе мы учим архитектурному подходу. Мы разбираем паттерны построения агентов, которые можно реализовать на любом языке (в том числе через Spring AI), или интегрировать Python-микросервисы в вашу Java-инфраструктуру. Реальные кейсы, разбор ошибок и фокус на Enterprise.
Ключевые темы:
— Паттерны надёжности (Retry, Fallback, Circuit Breaker) при работе с LLM.
— Интеграция с корпоративными Knowledge Base (RAG).
— Безопасность и контроль доступа (RBAC) в агентных системах.
Освоить проектирование AI-систем
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Задача из реального интервью в Google 👇
📦 Задание
Вы аналитик Google Ads. Нужно найти все объявления, которые:
— Имеют статус 'active'
— Показов больше 500,000
— Обновлены в 2024 году
Таблица google_ads на картинке. Напишите SQL-запрос для фильтрации.
Ставьте → 🔥, если нравится формат. Если нет → 🤔
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15🤔4👍3👏1
Собрали самые популярные и эффективные инструменты на все случаи жизни.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏1😁1
🐳 Магия Docker CLI
Если ты перезапускаешь контейнер или лезешь внутрь через exec, чтобы посмотреть процессы. То эта команда для тебя. Она показывает все процессы за секунду → docker top.
🔹 Зачем это нужно
— Показывает запущенные процессы внутри контейнера без входа в него.
— Видно PID, пользователя, нагрузку на CPU и команду запуска.
— Полезно для мониторинга и быстрой диагностики проблем с производительностью.
🔹 Как использовать
— Базовый вывод: docker top container_id
— С кастомным форматом (как ps): docker top container_id aux
— Можно фильтровать по пользователю или искать конкретный процесс.
— Удобно в скриптах для автоматизации проверок.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Если ты перезапускаешь контейнер или лезешь внутрь через exec, чтобы посмотреть процессы. То эта команда для тебя. Она показывает все процессы за секунду → docker top.
🔹 Зачем это нужно
— Показывает запущенные процессы внутри контейнера без входа в него.
— Видно PID, пользователя, нагрузку на CPU и команду запуска.
— Полезно для мониторинга и быстрой диагностики проблем с производительностью.
🔹 Как использовать
— Базовый вывод: docker top container_id
— С кастомным форматом (как ps): docker top container_id aux
— Можно фильтровать по пользователю или искать конкретный процесс.
— Удобно в скриптах для автоматизации проверок.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3❤1
Недавно в очередной раз столкнулся с холиваром: "Зачем ты переписал properties в yaml?" Давайте разбираться.
🔹 Properties — старая гвардия
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=admin
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
🔹 YAML — современный подход
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
password: secret
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
🔹 Технические нюансы
— Парсинг и производительность: properties парсится через java.util.Properties (простой key-value), YAML требует SnakeYAML библиотеку. На старте приложения разница незаметна, но YAML чуть медленнее из-за построения объектной модели.
— Приоритет загрузки: Spring Boot загружает конфиги в порядке: application.properties → application.yml → application-{profile}.properties → application-{profile}.yml. Если есть оба формата, properties имеет приоритет над yaml для одинаковых ключей.
— Списки и массивы: в YAML естественная запись списков, в properties приходится использовать индексы.
— Placeholder resolution: оба формата поддерживают ${variable:default}, но в YAML нужно быть осторожным с экранированием двоеточий в URL.
— Невалидный синтаксис: properties молча проигнорирует строку без =, YAML упадёт с исключением при старте приложения — это и минус, и плюс одновременно.
— @PropertySource ограничение: аннотация работает только с .properties, для YAML нужно писать кастомный PropertySourceFactory.
YAML для основной конфигурации приложения — структура и удобство работы со сложными объектами того стоят. Properties для специфичных кейсов: custom property sources с @PropertySource, legacy интеграции, простые CI/CD переменные, конфиги для библиотек без Spring контекста.
В production проектах часто вижу гибридный подход: application.yml для базовой структуры + application-{env}.properties для переопределения специфичных параметров окружения через environment variables.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤4🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥18😁14💯9👍3🙏1
Если ты хоть раз создавал Map<String, List<String>>, то пост для тебя.
Признай, каждый когда-нибудь писал:
Map<String, List<String>> userTags = new HashMap<>();
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("premium");
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("verified");
Или ещё хуже:
if (!userTags.containsKey("user123")) {
userTags.put("user123", new ArrayList<>());
}
userTags.get("user123").add("premium");Apache Commons Collections давно придумал MultiValuedMap.
🔹 Что это такое
MultiValuedMap<K, V> — это структура данных, которая позволяет хранить несколько значений для одного ключа. По сути, это Map<K, Collection<V>>, но с нормальным API.
MultiValuedMap<String, String> userTags = new ArrayListValuedHashMap<>();
userTags.put("user123", "premium");
userTags.put("user123", "verified");
userTags.put("user123", "early-adopter");
// Получаем все теги разом
Collection<String> tags = userTags.get("user123");
// [premium, verified, early-adopter]
Никаких computeIfAbsent, никаких проверок на null. Просто работает.
🔹 Что умеет
— Добавление без боли:
multiMap.put("key", "value1");
multiMap.put("key", "value2"); // не перезатирает предыдущее значение— Массовые операции:
multiMap.putAll("user456", Arrays.asList("admin", "moderator"));— Проверка наличия:
multiMap.containsMapping("user123", "premium"); // true/false— Удаление конкретного значения:
multiMap.removeMapping("user123", "premium");— Получение всех значений:
Collection<String> allTags = multiMap.values();
// все значения из всех ключей
🔹 Реализации
→ ArrayListValuedHashMap<K, V> — значения хранятся в ArrayList, порядок сохраняется, дубликаты разрешены
→ HashSetValuedHashMap<K, V> — значения хранятся в HashSet, без дубликатов
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23👍11👏2❤1