Реализация обновлений в реальном времени
Разрабатывайте резолверы подписок в Spring Boot для публикации событий и отправки клиентам актуальных данных.
«Реализация обновлений в реальном времени» — бесплатный урок GraphQL APIs with Spring Boot на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения GraphQL APIs with Spring Boot, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс GraphQL APIs with Spring Boot содержит 4 уроков всего.
Части этого урока еще не переведены и отображаются на английском.
Subscription Resolvers Explained
Subscriptions deliver real-time updates. Unlike queries that return data once, subscription resolvers return a stream of data that continuously pushes updates to clients.
We'll learn how to implement these streams in a Spring Boot GraphQL application.
Embracing Reactor Flux
Spring GraphQL leverages Project Reactor's Flux to handle subscriptions. A Flux represents an asynchronous, non-blocking stream of 0 to N items.
- It's ideal for continuous data delivery.
- You can emit multiple values over time.
Schema for Real-time Updates
First, we define our subscription in the GraphQL Schema Definition Language (SDL). This example shows a subscription for new messages:
type Subscription {
messageAdded(channelId: ID!): Message
}
type Message {
id: ID!
text: String!
channelId: ID!
timestamp: String!
}Creating a Subscription Resolver
In Spring Boot, a subscription resolver is a method annotated with @SubscriptionMapping. It must return a Flux of the desired type.
We'll use a Sinks.Many to manage and publish events into this stream.
import org.springframework.graphql.data.method.annotation.SubscriptionMapping;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;
@Controller
public class MessageSubscriptionController {
private final Sinks.Many<Message> messageSink =
Sinks.many().multicast().onBackpressureBuffer();
@SubscriptionMapping
public Flux<Message> messageAdded() {
return messageSink.asFlux();
}
}Publishing Events with Sinks.Many
The Sinks.Many instance acts as our event publisher. When an event occurs (e.g., a new message is created), we use its tryEmitNext() method to send data into the stream.
This data then flows through the Flux to all connected GraphQL subscribers.
public class MessageService {
private final Sinks.Many<Message> messageSink;
public MessageService(Sinks.Many<Message> messageSink) {
this.messageSink = messageSink;
}
public Message createMessage(String text, String channelId) {
// ... save message to DB ...
Message newMessage = new Message("1", text, channelId, "now");
messageSink.tryEmitNext(newMessage); // Publish the new message
return newMessage;
}
}Full Runnable Example Setup
Let's build a complete, runnable Spring Boot application. We'll define a Message record and a MessagePublisher component to manage our Sinks.Many.
record Message(String id, String text, String channelId, String timestamp) {}
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;
@Component
public class MessagePublisher {
private final Sinks.Many<Message> messageSink =
Sinks.many().multicast().onBackpressureBuffer();
public Flux<Message> getMessageStream() {
return messageSink.asFlux();
}
public void publishMessage(Message message) {
messageSink.tryEmitNext(message);
}
}Main Application & Resolver
Now, we connect our MessagePublisher to the @SubscriptionMapping resolver. The Main class simulates sending a message after a delay.
Run this example to see the server-side publishing in action!
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.graphql.data.method.annotation.SubscriptionMapping;
import org.springframework.stereotype.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
@SpringBootApplication
public class Main implements CommandLineRunner {
@Autowired
private MessagePublisher messagePublisher;
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Override
public void run(String... args) throws Exception {
// Simulate sending a message after 2 seconds
Mono.delay(Duration.ofSeconds(2))
.subscribe(l -> {
Message msg = new Message("2", "Hello from Spring!", "general", "now");
messagePublisher.publishMessage(msg);
System.out.println("Published: " + msg);
});
}
}
@Controller
class MessageSubscriptionController {
private final MessagePublisher messagePublisher;
public MessageSubscriptionController(MessagePublisher messagePublisher) {
this.messagePublisher = messagePublisher;
}
@SubscriptionMapping
public Flux<Message> messageAdded() {
return messagePublisher.getMessageStream();
}
}
record Message(String id, String text, String channelId, String timestamp) {}Filtering Subscription Events
Clients often need updates specific to certain criteria. We can filter the Flux based on arguments passed to the subscription.
Here, clients only receive messages for a specified channelId.
import org.springframework.graphql.data.method.annotation.Argument;
// ... other imports ...
@Controller
class MessageSubscriptionController {
private final MessagePublisher messagePublisher;
public MessageSubscriptionController(MessagePublisher messagePublisher) {
this.messagePublisher = messagePublisher;
}
@SubscriptionMapping
public Flux<Message> messageAdded(@Argument String channelId) {
return messagePublisher.getMessageStream()
.filter(msg -> msg.channelId().equals(channelId));
}
}Decoupling Event Publishing
For better architecture, it's a good practice to decouple event publishing from your core business logic.
- This keeps your services clean and focused.
- It allows multiple independent subscribers to react to the same event without tight coupling.
- Consider using Spring's
ApplicationEventPublisheror a dedicated event bus for this.
Subscription Resolver Check
You've learned how to implement subscription resolvers in Spring Boot. Let's test your understanding!
Recap: Real-time Updates
You've successfully learned how to implement real-time updates using GraphQL subscriptions in Spring Boot!
- Subscription resolvers return a
Flux. Sinks.Manyis used to publish events into theFlux.- You can filter streams based on subscription arguments.
- Decoupling publishing logic improves maintainability.
Часто задаваемые вопросы
Урок «Реализация обновлений в реальном времени» бесплатный?
Да — полный текст урока «Реализация обновлений в реальном времени» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс GraphQL APIs with Spring Boot, подпишись на CoddyKit PRO. Курс GraphQL APIs with Spring Boot содержит 4 уроков всего.
Чему я научусь в уроке «Реализация обновлений в реальном времени»?
Разрабатывайте резолверы подписок в Spring Boot для публикации событий и отправки клиентам актуальных данных. Ты практикуешь GraphQL APIs with Spring Boot с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать GraphQL APIs with Spring Boot?
Предыдущий опыт не требуется. GraphQL APIs with Spring Boot на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Реализация обновлений в реальном времени»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке GraphQL APIs with Spring Boot?
Да. Каждый урок GraphQL APIs with Spring Boot включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Понимание подписок GraphQL
- Реализация обновлений в реальном времени
- Интеграция WebSockets со Spring
- Фильтрация и масштабирование подписок