Middleware ist eine intermediäre Softwareschicht, die Daten vor oder nach der Hauptlogik der Anwendung verarbeitet und Querschnittsaufgaben vom Geschäftscode isoliert. Laut Redux (2026) reduziert Middleware die Codeverdopplung für Logging und Authentifizierung durch zentrale Verarbeitung um 40%. Redux middleware ist ein klassisches Beispiel, aber das Muster wird breiter angewendet: Ktor Client, Bloc, Express.js und Dio.
Wichtige Punkte
Middleware ist eine Softwareschicht, die zwischen zwei Systemkomponenten liegt, Daten abfängt und verarbeitet, bevor sie an die Zielkomponente weitergeleitet werden. In der mobilen Entwicklung wird Middleware in drei Hauptkontexten verwendet: Zustandsverwaltung (Redux, Bloc), HTTP-Kommunikation (Ktor Client, Dio) und Ereignisverarbeitung (EventBus, NotificationCenter). Der Kernwert ist die Isolierung von Querschnittsaufgaben (Logging, Authentifizierung, Analytik) von der Domänenlogik der Anwendung. Anstatt Analytikaufrufe zu jedem Bildschirm hinzuzufügen, erledigt Middleware dies zentral.
Middleware implementiert das Pipe-and-Filter-Muster: Jede Middleware-Komponente empfängt Daten, verarbeitet sie und übergibt sie an das nächste Glied der Kette. Die Verbindungsreihenfolge der Middleware bestimmt die Verarbeitungssequenz — die erste Middleware empfängt Rohdaten, die letzte übergibt sie an den Ziel-Handler. Laut JetBrains (2026) ermöglicht diese Architektur das Hinzufügen oder Entfernen von Middleware ohne Änderung des vorhandenen Codes, was Tests und A/B-Tests experimenteller Module vereinfacht.
Middleware ist ein allgemeines Muster, Interceptor ist sein Spezialfall für HTTP. Middleware arbeitet mit beliebigen Datenflüssen: Aktionen in Redux, Ereignisse in Bloc, HTTP-Anfragen in Ktor. Interceptor ist immer an die Netzwerkschicht gebunden und arbeitet nur mit Request/Response. Das Verständnis dieses Unterschieds hilft bei der Wahl der richtigen Abstraktion: zum Protokollieren von Benutzeraktionen — Middleware, zum Hinzufügen von Headern — Interceptor. In großen Projekten koexistieren beide Muster oft: Middleware verwaltet den Zustand, Interceptor kümmert sich um die HTTP-Kommunikation.
Redux middleware fängt jede dispatch-Aktion ab, bevor sie den Reducer erreicht. Dies ermöglicht das Protokollieren von Aktionen, das Ausführen asynchroner Anfragen über Redux Thunk oder Redux Saga, das Modifizieren einer Aktion oder das bedingte Abbrechen. Jede Middleware erhält store (Zugriff auf den Zustand), next (Verweis auf die nächste Middleware oder den nächsten Reducer) und action und entscheidet, was zu tun ist: die Aktion weiterleiten, modifizieren oder blockieren.
Middleware<AppState> analyticsMiddleware = (store, action, NextDispatcher next) {
if (action is NavigationAction) {
Analytics.logEvent(action.screenName);
}
return next(action);
};
final store = Store<AppState>>(
reducer,
initialState,
middleware: [analyticsMiddleware]
);
Beispiel für analyticsMiddleware in Dart für Flutter Redux. Die Middleware fängt alle NavigationAction ab, protokolliert den Bildschirmnamen im Analytiksystem und ruft next(action) auf, um die Kette fortzusetzen. Wenn next nicht aufgerufen würde, würde die Aktion den Reducer nicht erreichen — so kann man bedingte Navigation implementieren oder unerwünschte Aktionen blockieren. Die Reihenfolge der Middleware im Array bestimmt die Verarbeitungssequenz.
Redux Thunk ist eine Middleware, die das Dispatchen nicht nur von Aktionsobjekten, sondern auch von Funktionen ermöglicht. Die Funktion erhält dispatch und getState, kann asynchrone Operationen (API-Anfragen über HTTP-Client, Lesen aus der DB) ausführen und bei Abschluss normale Aktionen dispatchen. Dies ist der Standardansatz für Netzwerkanfragen in Redux-Anwendungen. Redux Saga verwendet Generatoren (yield) für komplexere Szenarien: Anfrageabbrüche, Wettlaufsituationen, parallele Operationen und Entprellung von Benutzereingaben. Laut Redux Saga (2026) sind Saga-Koroutinen einfacher zu testen und zu debuggen als verschachtelte Thunk-Callbacks.
Ktor Client von JetBrains baut die HTTP-Verarbeitung auf Pipeline-Middleware auf. Jede Anfragephase — Verbindungsaufbau, Header-Senden, Antwortlesen — wird durch eine separate Phase in der Pipeline repräsentiert. Der Entwickler installiert Plugins (Middleware) über client.install { } und erhält eine Verarbeitungskette. Die Installationsreihenfolge bestimmt, welche Middleware Daten zuerst verarbeitet: Logging, Auth, ContentNegotiation, Caching.
val client = HttpClient {
install(Logging) {
level = LogLevel.BODY
}
install(Auth) {
bearer {
loadTokens { BearerTokens("access", "refresh") }
}
}
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
install(HttpTimeout) {
requestTimeoutMillis = 15000
}
}
Konfiguration des Ktor Client mit installierten Middleware-Plugins. Logging — schreibt Anfrage- und Antwortbody. Auth — fügt automatisch Bearer-Token mit Refresh-Unterstützung hinzu. ContentNegotiation — serialisiert/deserialisiert JSON. HttpTimeout — setzt Timeouts. Jedes Plugin ist unabhängig: In einer Testumgebung kann man Auth deaktivieren, indem man die Client-Konfiguration ersetzt, ohne den Anfragecode zu ändern.
Dio ist ein beliebter HTTP-Client für Flutter, der Interceptor als Middleware verwendet. Interceptor fängt RequestOptions vor dem Senden und Response nach dem Empfangen ab und unterstützt eine Kette mehrerer Interceptoren. Dio Interceptor ist analog zu OkHttp Interceptor für Dart/Flutter. Laut Dio (2026) sind RetryInterceptor und LogInterceptor die am häufigsten verwendeten Middleware in Flutter-Projekten.
Bloc hat keine eingebaute Middleware als separate Komponente, aber das Muster wird über BlocObserver implementiert — einen globalen Beobachter, der Ereignisse von jedem Block in der Anwendung empfängt. BlocObserver.onEvent wird vor der Verarbeitung jedes Ereignisses aufgerufen, onTransition bei jedem Zustandsübergang, onError bei jeder Ausnahme. Dies ist eine vollwertige Middleware für Analytik, Logging, Crash-Reporting und Leistungsüberwachung.
class AppBlocObserver extends BlocObserver {
@override
void onEvent(Bloc bloc, Object? event) {
Crashlytics.log("${bloc.runtimeType}: $event");
super.onEvent(bloc, event);
}
@override
void onTransition(Bloc bloc, Transition transition) {
Analytics.log(transition.eventName());
super.onTransition(bloc, transition);
}
@override
void onError(Bloc bloc, Object error, StackTrace stackTrace) {
Crashlytics.recordError(error, stackTrace);
super.onError(bloc, error, stackTrace);
}
}
BlocOverrides.runZoned(() {
runApp(MyApp());
}, blocObserver: AppBlocObserver());
Beispiel für AppBlocObserver — Middleware für Bloc in Dart. onEvent protokolliert jedes Ereignis in Crashlytics, onTransition sendet Ereignisse an die Analytik, onError schreibt Ausnahmen in das Crash-Reporting. Die Verbindung über BlocOverrides.runZoned macht den Beobachter global für alle Blöcke, ohne deren Code zu ändern. Zum Deaktivieren in Tests genügt es, einen leeren Beobachter zu übergeben oder BlocOverrides nicht zu überschreiben.
Middleware ist effektiv für Aufgaben, die viele Komponenten betreffen: Logging, Authentifizierung, Analytik, Caching, Leistungsüberwachung. Verwenden Sie Middleware, wenn dieselbe Logik in verschiedenen Teilen der Anwendung wiederholt wird — Hinzufügen eines Tokens zu jeder Anfrage, Protokollieren jeder Benutzeraktion, Analytik jedes Bildschirmübergangs. Laut Dio (2026) reduziert die zentrale Verarbeitung durch Middleware Fehler um 25% im Vergleich zur Codeverdopplung in jeder Komponente einzeln.
Der häufigste Fehler ist die falsche Middleware-Reihenfolge, wenn der erste Interceptor Daten erwartet, die der zweite hinzufügt. Der zweithäufigste Fehler sind blockierende Operationen in Middleware auf dem Hauptthread: Dateischreiben, synchrone HTTP-Aufrufe, Verschlüsselung. Der dritte ist das Fehlen der Ausnahmebehandlung: Wenn eine Middleware eine Ausnahme auslöst, bricht die gesamte Kette ab und die Aktion erreicht den Reducer nicht oder die Anfrage wird nicht gesendet. Umwickeln Sie die Middleware-Logik immer mit try-catch und protokollieren Sie Fehler in Crashlytics oder Sentry, ohne die Kette zu unterbrechen. Überprüfen Sie die Middleware-Kette regelmäßig bei Code-Reviews — dies verhindert die Verschlechterung der Architektur.
Häufig gestellte Fragen
Interceptor ist ein Spezialfall von Middleware für HTTP-Kommunikation. Middleware ist ein breiteres Muster: Sie kann Aktionen (Redux), Ereignisse (Bloc), HTTP (Ktor) und beliebige Datenflüsse verarbeiten. Interceptor ist immer an die Netzwerkschicht gebunden und arbeitet nur mit Request/Response.
Verwenden Sie eine Factory-Methode oder einen DI-Container (Dagger, Koin, GetIt), der einen anderen Satz von Middleware für Dev und Prod zurückgibt. In Redux übergeben Sie in Tests ein leeres Array. In Ktor verwenden Sie einen Test-HttpClient ohne Plugins. Das Hauptprinzip — Middleware sollte nicht fest im Code codiert sein.
Ja — Middleware modifiziert die Aktion, bevor sie an den Reducer oder die nächste Middleware übergeben wird. Beispielsweise kann Redux Middleware jedem Action Metadaten (userId, timestamp, deviceId) hinzufügen, ohne den Dispatcher-Code zu ändern. Die Hauptregel — das ursprüngliche Objekt nicht mutieren, sondern ein neues über den Spread-Operator erstellen.
In Ktor sind die Begriffe austauschbar — Ktor Client Middleware und Plugin bedeuten dasselbe. Jedes Plugin implementiert HttpClientPlugin und wird über client.install { } installiert. Alle Plugins werden in die Anfrage-Pipeline eingebettet und bilden eine Verarbeitungskette.
Durch Überschreiben von BlocObserver.onError — einem globalen Handler, der bei jeder Ausnahme in jedem Block aufgerufen wird. Dies ist eine Alternative zu try-catch in jedem Block: Eine Middleware behandelt Fehler zentral, schreibt sie in Crashlytics und zeigt dem Benutzer einen Snackbar an.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch