[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-reactive-chto-takoe-context-v-project-reactor":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},1004,"chto-takoe-context-v-project-reactor",31,"reactive","Reactive","⚡","Что такое Context в Project Reactor?","Context — неизменяемая (immutable) структура данных в Project Reactor, привязанная к конкретной подписке (Subscription). Замена ThreadLocal для реактивных цепочек, где один запрос может исполняться в разных потоках.\n\n> Аналогия из жизни: Context — это как бейджик участника конференции. Не важно, в какой зал (поток) вы перейдёте — бейджик (контекст) остаётся при вас и идентифицирует вас в любом месте.\n\n### Проблема\n\nВ реактивном коде ThreadLocal не работает, потому что цепочка операторов может переключаться между потоками через `publishOn`\u002F`subscribeOn`. Context решает эту проблему.\n\n### Запись и чтение контекста\n\n```java\nMono\u003CString> mono = Mono.deferContextual(ctx -> {\n        String userId = ctx.get(\"userId\");\n        return Mono.just(\"User: \" + userId);\n    })\n    .contextWrite(Context.of(\"userId\", \"12345\"));\n\u002F\u002F Результат: \"User: 12345\"\n```\n\n\u003Cdetails>\u003Csummary>Практический пример — передача correlation ID\u003C\u002Fsummary>\n\n```java\n@Component\npublic class CorrelationWebFilter implements WebFilter {\n\n    @Override\n    public Mono\u003CVoid> filter(ServerWebExchange exchange, WebFilterChain chain) {\n        String correlationId = exchange.getRequest().getHeaders()\n            .getFirst(\"X-Correlation-ID\");\n        if (correlationId == null) {\n            correlationId = UUID.randomUUID().toString();\n        }\n        String finalCorrelationId = correlationId;\n        return chain.filter(exchange)\n            .contextWrite(Context.of(\"correlationId\", finalCorrelationId));\n    }\n}\n\n\u002F\u002F Использование в сервисе\n@Service\npublic class OrderService {\n\n    public Mono\u003COrder> createOrder(OrderRequest request) {\n        return Mono.deferContextual(ctx -> {\n            String correlationId = ctx.getOrDefault(\"correlationId\", \"unknown\");\n            log.info(\"[{}] Создание заказа\", correlationId);\n            return orderRepository.save(new Order(request));\n        });\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Важные особенности\n\n- Context immutable — каждый `contextWrite` создаёт новый Context\n- Context распространяется снизу вверх (от subscribe к источнику) — `contextWrite` должен быть ниже точки чтения\n- `deferContextual` — для чтения контекста при создании элементов\n- `transformDeferredContextual` — для трансформации в середине цепочки\n\n```java\n\u002F\u002F Ближний к подписке contextWrite перезаписывает дальний\nMono\u003CString> mono = Mono.deferContextual(ctx ->\n        Mono.just(ctx.get(\"key\")))\n    .contextWrite(ctx -> ctx.put(\"key\", \"value2\"))  \u002F\u002F ближе к подписке\n    .contextWrite(ctx -> ctx.put(\"key\", \"value1\")); \u002F\u002F дальше от подписки\n\u002F\u002F Результат: \"value2\"\n```\n\n### Частые ошибки\n\n- Использовать ThreadLocal в реактивном коде — значение потеряется при смене потока\n- Помещать `contextWrite` выше точки чтения — Context распространяется снизу вверх\n- Хранить мутабельные объекты в Context — лучше использовать immutable типы\n- Злоупотреблять Context — это не замена параметров метода; Context для cross-cutting concerns (tracing, auth, MDC)\n\n### Как используется в 2026\n\n- Reactor Context — стандарт для передачи correlation ID, trace ID, информации об аутентификации\n- Micrometer + Reactor автоматически пробрасывает observation context через Reactor Context\n- Spring Security Reactive использует Context для хранения SecurityContext\n- С Virtual Threads потребность снижается (можно использовать ThreadLocal через ScopedValue)\n\n> **На собеседовании:** ключевое — объяснить, зачем нужен Context (замена ThreadLocal) и что он распространяется снизу вверх. Частая ошибка — не знать направление распространения Context и разместить contextWrite выше точки чтения.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Что такое Sinks в Project Reactor? — Gymterview","Sinks — программно управляемые издатели данных в Project Reactor, пришедшие на замену deprecated FluxProcessor и MonoProcessor (Reactor 3.4+). Sinks позволяют и","Sinks — программно управляемые издатели данных в Project Reactor, пришедшие на замену deprecated FluxProcessor и MonoPro",[7,13],"Sinks — программно управляемые издатели данных в Project Reactor, пришедшие на замену deprecated FluxProcessor и MonoProcessor (Reactor 3.4+). Sinks позволяют императивно отправлять данные в реактивный поток.",true]