Ich habe nach der Verwaltung einer REST-API-Version mit Spring 3.2.x gesucht, aber nichts gefunden, das einfach zu warten ist. Ich werde zuerst das Problem erklären, das ich habe, und dann eine Lösung ... aber ich frage mich, ob ich das Rad hier neu erfinde.
Ich möchte die Version basierend auf dem Accept-Header verwalten. Wenn eine Anforderung beispielsweise den Accept-Header enthält application/vnd.company.app-1.1+json
, möchte ich, dass Spring MVC diese an die Methode weiterleitet, die diese Version verarbeitet. Und da sich nicht alle Methoden in einer API in derselben Version ändern, möchte ich nicht zu jedem meiner Controller gehen und etwas für einen Handler ändern, der sich zwischen den Versionen nicht geändert hat. Ich möchte auch nicht die Logik haben, um herauszufinden, welche Version im Controller selbst verwendet werden soll (mithilfe von Service Locators), da Spring bereits herausfindet, welche Methode aufgerufen werden soll.
Wenn ich also eine API mit den Versionen 1.0 bis 1.8 nehme, in der ein Handler in Version 1.0 eingeführt und in Version 1.7 geändert wurde, möchte ich dies folgendermaßen behandeln. Stellen Sie sich vor, der Code befindet sich in einem Controller und es gibt Code, der die Version aus dem Header extrahieren kann. (Folgendes ist im Frühjahr ungültig)
@RequestMapping(...)
@VersionRange(1.0,1.6)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(...) //same Request mapping annotation
@VersionRange(1.7)
@ResponseBody
public Object method2() {
// so something
return object;
}
Dies ist im Frühjahr nicht möglich, da die beiden Methoden dieselbe RequestMapping
Anmerkung haben und Spring nicht geladen werden kann. Die Idee ist, dass die VersionRange
Annotation einen offenen oder geschlossenen Versionsbereich definieren kann. Die erste Methode ist ab Version 1.0 bis 1.6 gültig, die zweite ab Version 1.7 (einschließlich der neuesten Version 1.8). Ich weiß, dass dieser Ansatz bricht, wenn sich jemand entscheidet, Version 99.99 zu bestehen, aber damit kann ich leben.
Da das oben Genannte nicht möglich ist, ohne ernsthaft zu überarbeiten, wie der Frühling funktioniert, habe ich darüber nachgedacht, an der Art und Weise zu basteln, wie Handler auf Anforderungen abgestimmt sind, insbesondere meine eigenen zu schreiben ProducesRequestCondition
und den Versionsbereich dort zu haben. Beispielsweise
Code:
@RequestMapping(..., produces = "application/vnd.company.app-[1.0-1.6]+json)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(..., produces = "application/vnd.company.app-[1.7-]+json)
@ResponseBody
public Object method2() {
// so something
return object;
}
Auf diese Weise kann ich geschlossene oder offene Versionsbereiche im Erzeugerteil der Annotation definieren. Ich arbeite gerade an dieser Lösung nun mit dem Problem , dass ich noch einige Kerne Spring MVC Klassen hatte zu ersetzen ( RequestMappingInfoHandlerMapping
, RequestMappingHandlerMapping
und RequestMappingInfo
), die ich nicht mag, weil es zusätzliche Arbeit bedeutet , wenn ich auf eine neuere Version von Upgrade entscheiden Frühling.
Ich würde mich über Gedanken freuen ... und insbesondere über Vorschläge, dies auf einfachere und leichter zu pflegende Weise zu tun.
Bearbeiten
Kopfgeld hinzufügen. Um das Kopfgeld zu erhalten, beantworten Sie bitte die obige Frage, ohne vorzuschlagen, diese Logik im Controller selbst zu haben. Spring hat bereits eine Menge Logik, um die aufzurufende Controller-Methode auszuwählen, und ich möchte darauf zurückgreifen.
Bearbeiten 2
Ich habe den ursprünglichen POC (mit einigen Verbesserungen) in Github geteilt: https://github.com/augusto/restVersioning
produces={"application/json-1.0", "application/json-1.1"}
usw.