Ich möchte meine RESTful-API sehr vorhersehbar machen. Was ist die beste Vorgehensweise, um zu entscheiden, wann eine Segmentierung von Daten mithilfe des URI und nicht mithilfe von Abfrageparametern vorgenommen werden soll?
Für mich ist es sinnvoll, dass Systemparameter, die Paginierung, Sortierung und Gruppierung unterstützen, nach dem '?' Aber was ist mit Feldern wie "Status" und "Region" oder anderen Attributen, die Ihre Sammlung segmentieren? Wenn dies auch Abfrageparameter sein sollen, wie lautet die Faustregel, wenn Sie wissen, wann Pfadparameter verwendet werden sollen?
Antworten:
Die bewährte Methode für das RESTful-API-Design besteht darin, dass Pfadparameter zum Identifizieren einer bestimmten Ressource oder von bestimmten Ressourcen verwendet werden, während Abfrageparameter zum Sortieren / Filtern dieser Ressourcen verwendet werden.
Hier ist ein Beispiel. Angenommen, Sie implementieren RESTful-API-Endpunkte für eine Entität namens Car. Sie würden Ihre Endpunkte folgendermaßen strukturieren:
GET
/cars
GET
/cars/:id
POST
/cars
PUT
/cars/:id
DELETE
/cars/:id
Auf diese Weise verwenden Sie nur Pfadparameter, wenn Sie angeben, welche Ressource abgerufen werden soll. Dadurch werden die Ressourcen jedoch in keiner Weise sortiert / gefiltert.
Angenommen, Sie möchten die Möglichkeit hinzufügen, die Autos in Ihren GET-Anforderungen nach Farbe zu filtern. Da Farbe keine Ressource ist (es ist eine Eigenschaft einer Ressource), können Sie einen Abfrageparameter hinzufügen, der dies tut. Sie würden diesen Abfrageparameter wie folgt zu Ihrer GET-
/cars
Anforderung hinzufügen :BEKOMMEN
/cars?color=blue
Dieser Endpunkt würde so implementiert, dass nur blaue Autos zurückgegeben würden.
In Bezug auf die Syntax sollten Ihre URL-Namen nur in Kleinbuchstaben geschrieben sein. Wenn Sie einen Entitätsnamen haben, der im Allgemeinen aus zwei englischen Wörtern besteht, würden Sie einen Bindestrich verwenden, um die Wörter zu trennen, nicht die Groß- und Kleinschreibung.
Ex.
/two-words
quelle
Die grundlegende Art, über dieses Thema nachzudenken, ist wie folgt:
Ein URI ist eine Ressourcenkennung, die eine bestimmte Instanz eines Ressourcentyps eindeutig identifiziert. Wie alles andere im Leben hat jedes Objekt (das eine Instanz eines Typs ist) eine Reihe von Attributen, die entweder zeitinvariant oder zeitlich sind.
Im obigen Beispiel ist ein Auto ein sehr greifbares Objekt mit Attributen wie Marke, Modell und Fahrgestellnummer, die sich nie ändern, sowie Farbe, Federung usw., die sich im Laufe der Zeit ändern können. Wenn wir also den URI mit Attributen codieren, die sich im Laufe der Zeit (zeitlich) ändern können, erhalten wir möglicherweise mehrere URIs für dasselbe Objekt:
Und Jahre später, wenn die Farbe dieses Autos in Schwarz geändert wird:
Beachten Sie, dass sich die Autoinstanz selbst (das Objekt) nicht geändert hat - es ist nur die Farbe, die sich geändert hat. Wenn mehrere URIs auf dieselbe Objektinstanz verweisen, müssen Sie mehrere URI-Handler erstellen. Dies ist kein effizientes Design und natürlich nicht intuitiv.
Daher sollte der URI nur aus Teilen bestehen, die sich niemals ändern und diese Ressource während ihrer gesamten Lebensdauer eindeutig identifizieren. Alles, was sich ändern kann, sollte als solches für Abfrageparameter reserviert werden:
Fazit: Denken Sie an Polymorphismus.
quelle
In einer REST-API sollten Sie nicht übermäßig von vorhersehbaren URIs betroffen sein. Der bloße Vorschlag der URI-Vorhersagbarkeit spielt auf ein Missverständnis der RESTful-Architektur an. Es wird davon ausgegangen, dass ein Client selbst URIs erstellt, die er eigentlich nicht haben sollte.
Ich gehe jedoch davon aus, dass Sie keine echte REST-API erstellen, sondern eine von REST inspirierte API (wie die von Google Drive). In diesen Fällen lautet die Faustregel "Pfadparameter = Ressourcenidentifikation" und "Abfrageparameter = Ressourcensortierung". Es stellt sich also die Frage, ob Sie Ihre Ressource OHNE Status / Region eindeutig identifizieren können. Wenn ja, dann ist es vielleicht ein Abfrageparameter. Wenn nein, dann ist es ein Pfadparameter.
HTH.
quelle
Einmal habe ich eine API entworfen, welche Hauptressource war
people
. Normalerweisepeople
forderten Benutzer gefiltert an , um zu verhindern, dass Benutzer so etwas wie/people?settlement=urban
jedes Mal aufrufen. Ich implementierte dies,/people/urban
was mir später das einfache Hinzufügen ermöglichte/people/rural
. Dies ermöglicht auch den Zugriff auf die vollständige/people
Liste, falls diese später von Nutzen sein sollte. Kurz gesagt, meine Argumentation war, einen Pfad zu allgemeinen Teilmengen hinzuzufügenVon hier aus :
quelle
Im Allgemeinen tendiere ich dazu, Pfadparameter zu verwenden, wenn die Ressource eine offensichtliche "Hierarchie" aufweist, wie z.
Wenn diese einzelne Ressource einen Status hat, könnte man:
Wenn 'region' jedoch nicht wirklich Teil der offengelegten Ressource ist, gehört es wahrscheinlich zu einem der Abfrageparameter - ähnlich wie bei der Paginierung (wie Sie erwähnt haben).
quelle
Die Segmentierung ist hierarchischer und "hübscher", kann jedoch einschränkend sein.
Wenn Sie beispielsweise eine URL mit drei Segmenten haben, die jeweils unterschiedliche Parameter übergeben, um über Marke, Modell und Farbe nach einem Auto zu suchen:
Dies ist eine sehr hübsche URL, an die sich der Endbenutzer leichter erinnern kann, aber jetzt bleibt Ihre Art bei dieser Struktur. Angenommen, Sie möchten es so gestalten, dass der Benutzer bei der Suche nach ALLEN blauen Autos oder ALLEN Honda Civics suchen kann? Ein Abfrageparameter löst dies, weil er ein Schlüsselwertpaar ergibt. Sie könnten also bestehen:
Jetzt haben Sie die Möglichkeit, den Wert über seinen Schlüssel zu referenzieren - entweder "color" oder "make" in Ihrem Abfragecode.
Sie könnten dies umgehen, indem Sie möglicherweise mehr Segmente verwenden, um eine Art Schlüsselwertstruktur zu erstellen, wie:
Hoffe das macht Sinn ..
quelle
Beispiel-URL:
/rest/{keyword}
Diese URL ist ein Beispiel für Pfadparameter. Wir können diese URL-Daten mithilfe von erhalten
@PathParam
.Beispiel-URL:
/rest?keyword=java&limit=10
Diese URL ist ein Beispiel für Abfrageparameter. Wir können diese URL-Daten mithilfe von erhalten
@Queryparam
.quelle