Parametry macierzy adresów URL a parametry zapytań

176

Zastanawiam się, czy używać parametrów macierzy lub zapytania w moich adresach URL. Starsza dyskusja na ten temat nie była satysfakcjonująca.

Przykłady

Na pierwszy rzut oka parametry macierzy wydają się mieć tylko zalety:

  • bardziej czytelne
  • nie jest wymagane kodowanie ani dekodowanie znaku „&” w dokumentach XML
  • Adresy URL z „?” w wielu przypadkach nie są buforowane; Adresy URL z parametrami macierzy są buforowane
  • parametry macierzy mogą pojawić się wszędzie na ścieżce i nie są ograniczone do jej końca
  • parametry macierzy mogą mieć więcej niż jedną wartość: paramA=val1,val2

Ale są też wady:

  • tylko kilka frameworków, takich jak JAX-RS, obsługuje parametry macierzy
  • Kiedy przeglądarka przesyła formularz za pomocą GET, parametry stają się parametrami zapytania. Tak więc kończy się na dwóch rodzajach parametrów dla tego samego zadania. Aby nie mylić użytkowników usług REST i nie ograniczać wysiłku twórców usług, łatwiej byłoby zastosować zawsze parametry zapytania - w tym obszarze.

Ponieważ twórca usługi może wybrać framework z obsługą parametrów macierzy, jedyną pozostałą wadą byłoby to, że przeglądarki tworzą domyślne parametry zapytań.

Czy są jakieś inne wady? Co byś zrobił?

demon
źródło
10
Nie jestem pewien, o co chodzi z macierzowymi adresami URL. Zgodnie z artykułem o projekcie w3c napisanym przez TBL, był to tylko pomysł na projekt i wyraźnie stwierdza, że nie jest to funkcja sieci. Rzeczy takie jak względne adresy URL nie są implementowane podczas korzystania z niego. Jeśli chcesz go użyć, w porządku; po prostu nie ma standardowego sposobu używania go, ponieważ nie jest to standard.
Steve Pomeroy
2
@Steve Pomeroy: Czy to artykuł, o którym wspominasz: w3.org/DesignIssues/MatrixURIs.html
Marcel
3
@Marcel: tak. Ci, którzy myślą o matrycowych adresach URL, powinni zwrócić uwagę na „Stan: widok osobisty” u góry dokumentu.
Steve Pomeroy
czy parametry macierzy mogą mieć więcej niż jedną wartość? naprawdę?
Ayyash

Odpowiedzi:

212

Istotna różnica polega na tym, że parametry macierzy mają zastosowanie do określonego elementu ścieżki, podczas gdy parametry zapytania mają zastosowanie do żądania jako całości. Ma to znaczenie podczas tworzenia złożonego zapytania w stylu REST do wielu poziomów zasobów i zasobów podrzędnych:

http://example.com/res/categories;name=foo/objects;name=green/?page=1

To naprawdę sprowadza się do przestrzeni nazw.

Uwaga: „poziomy” zasobów to categoriesi objects.

Gdyby tylko parametry zapytania zostały użyte dla wielopoziomowego adresu URL, otrzymałeś

http://example.com/res?categories_name=foo&objects_name=green&page=1

W ten sposób stracisz również przejrzystość dodaną przez lokalizację parametrów w żądaniu. Ponadto w przypadku korzystania ze struktury takiej jak JAX-RS wszystkie parametry zapytania pojawiałyby się w każdym programie obsługi zasobów, co prowadziło do potencjalnych konfliktów i zamieszania.

Jeśli zapytanie ma tylko jeden „poziom”, różnica nie jest tak naprawdę ważna, a te dwa typy parametrów są efektywnie zamienne, jednak parametry zapytania są ogólnie lepiej obsługiwane i szerzej rozpoznawane. Ogólnie zalecałbym, abyś trzymał się parametrów zapytań, takich jak formularze HTML i proste, jednopoziomowe interfejsy HTTP API.

Tim Sylvester
źródło
2
irrelavant: czy /?część reprezentuje zasób?
Jin Kwon
7
?Rozpoczyna część parametru zapytania wniosku. Parametry zapytania to najpopularniejszy typ parametrów adresu URL, w przeciwieństwie do parametrów macierzy. Ukośnik przed znakiem zapytania gwarantuje, że parametr zapytania pagenie trafi do parametru macierzy, który poprzedza ukośnik. Przypuszczam, że gdyby nie było dołączonych parametrów macierzy, parametry categorieszapytania mogłyby zostać dołączone bez ukośnika w następujący sposób:http://example.com/res/categories?page=1
Teemu Leisti
8
Chociaż prawdą jest, że parametry macierzy mogą być określone w dowolnym segmencie ścieżki, na przykład JAX-RS nie kojarzy ich z segmentem ścieżki, do którego zostały dołączone podczas wstrzykiwania @MatrixParam. Zgodnie z „Restful Java with JAX-RS 2.0” żądanie takie jak „GET / mercedes / e55; kolor = czarny / 2006 / wnętrze; kolor = tan” miałoby niejednoznaczną definicję parametru macierzy kolorów. Chociaż wygląda na to, że przetwarzając każdy segment PathSegment indywidualnie, możesz to rozgryźć ... Tak przydatne, ale więcej pracy, aby do niego dotrzeć, niż gdybyś określił categoryName = foo; objectName = green.
UFL1138
15

Oprócz odpowiedzi Tima Sylvestera chciałbym podać przykład, w jaki sposób parametry macierzy mogą być obsługiwane przez JAX-RS .

  1. Parametry macierzy w ostatnim elemencie zasobu

    http://localhost:8080/res/categories/objects;name=green

    Możesz uzyskać do nich dostęp za pomocą @MatrixParamadnotacji

    @GET
    @Path("categories/objects")
    public String objects(@MatrixParam("name") String objectName) {
      return objectName;
    }

    Odpowiedź

    green

    Ale tak jak stwierdza Javadoc

    Należy zauważyć, że @MatrixParamwartość adnotacji odnosi się do nazwy parametru macierzy, który znajduje się w ostatnim dopasowanym segmencie ścieżki struktury Java z adnotacją Path, która wstrzykuje wartość parametru matrix.

    ... co prowadzi nas do punktu 2

  2. Parametry macierzy w środku adresu URL

    http://localhost:8080/res/categories;name=foo/objects;name=green

    Dostęp do parametrów macierzy można uzyskać w dowolnym miejscu za pomocą zmiennych ścieżki i @PathParam PathSegment.

    @GET
    @Path("{categoryVar:categories}/objects")
    public String objectsByCategory(@PathParam("categoryVar") PathSegment categorySegment, 
                                    @MatrixParam("name") String objectName) {
      MultivaluedMap<String, String> matrixParameters = categorySegment.getMatrixParameters();
      String categorySegmentPath = categorySegment.getPath();
      String string = String.format("object %s, path:%s, matrixParams:%s%n", objectName,
              categorySegmentPath, matrixParameters);
      return string;
    }

    Odpowiedź

    object green, path:categories, matrixParams:[name=foo]

    Ponieważ parametry macierzy są dostarczane jako MultivaluedMap, do każdego z nich można uzyskać dostęp za pomocą

    List<String> names = matrixParameters.get("name");

    lub jeśli potrzebujesz tylko pierwszego

    String name = matrixParameters.getFirst("name");
  3. Pobierz wszystkie parametry macierzy jako jeden parametr metody

    http://localhost:8080/res/categories;name=foo/objects;name=green//attributes;name=size

    Użyj, List<PathSegment>aby zdobyć je wszystkie

    @GET
    @Path("all/{var:.+}")
    public String allSegments(@PathParam("var") List<PathSegment> pathSegments) {
      StringBuilder sb =  new StringBuilder();
    
      for (PathSegment pathSegment : pathSegments) {
        sb.append("path: ");
        sb.append(pathSegment.getPath());
        sb.append(", matrix parameters ");
        sb.append(pathSegment.getMatrixParameters());
        sb.append("<br/>");
      }
    
      return sb.toString();
    }

    Odpowiedź

    path: categories, matrix parameters [name=foo]
    path: objects, matrix parameters [name=green]
    path: attributes, matrix parameters [name=size]
René Link
źródło
10

--Zbyt ważne, by zostać zdegradowanym do sekcji komentarzy. -

Nie jestem pewien, o co chodzi z macierzowymi adresami URL. Zgodnie z artykułem o projekcie w3c, napisanym przez TBL, był to tylko pomysł na projekt i wyraźnie stwierdza, że ​​nie jest to funkcja sieci. Rzeczy takie jak względne adresy URL nie są implementowane podczas korzystania z niego. Jeśli chcesz go użyć, to w porządku; po prostu nie ma standardowego sposobu korzystania z niego, ponieważ nie jest to standard. - Steve Pomeroy

Krótka odpowiedź brzmi: jeśli potrzebujesz RS do celów biznesowych, lepiej jest użyć parametru żądania.

Ajeet Ganga
źródło
5
Ktoś powie to deweloperom Angular 2, którzy zdecydowali, że są tak wyjątkowi, że zamiast tego musieli to zaimplementować!
Matt Pileggi,
2
@MattPileggi Czytam to również ze względu na Angular 2. Prawie każdy aspekt Angular 2 jest wysoce wyspecjalizowany, niekonwencjonalny i sprzeczny z istniejącymi wzorcami użytkowania. Nie udowodniono jeszcze, że ma to wartość łagodzącą.
Aluan Haddad
1
Więc, chłopaki, jestem tu również z tego samego powodu, ale pozwólcie, że dodam kilka punktów do tej dyskusji w tym problemie dotyczącym macierzy adresów URL i Google Analytics na stronie github zespołu Angular 2: github.com/angular/angular/issues/11740 Ale po kilku badaniach na ten temat notacja macierzy url wydaje się być bardziej czytelna dla człowieka niż parametry zapytania url , głównie wtedy, gdy potrzebujemy jakiegoś parametru w środku lub url (nie tylko na końcu).
Richard Lee
8
Chyba każdy, kto uważa, że ​​jest to niestandardowe, nie jest też zaznajomiony ze specyfikacją szablonu URI? Kodowanie złożonych obiektów w parametrach ścieżki jest bardzo przydatną funkcją szablonów uri; tylko dlatego, że większość ludzi o tym nie wie lub nie używa, nie oznacza, że ​​jest to jakiś zły spisek twórców kątowych, aby wprowadzić bezużyteczną złożoność do twojego życia.
Ajax
2
Pffft - „<rzecz, o której istnieniu nie wiedziałem do tej pory> jest niestandardowa, zachowując w ten sposób akceptowalność mojej ignorancji”. To, co TBL zrobił lub nie zdecydował się zrobić z pomysłem, jest w dużej mierze nieistotne. Nie była to funkcja jego sieci w 2001 roku. Funkcje sieci są takie, jakie wybiorą klienci i wdrażający serwer. Jeśli Angular obsługuje parametry macierzy, a JAX-RS je obsługuje i są to wybrane przez Ciebie narzędzia implementacyjne, to używaj tego, co działa.
Dave,