Jaki jest najlepszy sposób uzyskania aktualnego adresu URL w Spring MVC?

97

Chciałbym utworzyć adresy URL na podstawie adresu URL używanego przez klienta dla aktywnego żądania. Czy jest coś mądrzejszego niż pobranie bieżącego HttpServletRequestobiektu i jego getParameter...()metod przebudowy całego adresu URL, w tym (i tylko) jego parametrów GET.

Wyjaśnienie: Jeśli to możliwe, chcę zrezygnować z używania HttpServletRequestprzedmiotu.

Koraktor
źródło

Odpowiedzi:

112

Istnieją dwie metody łatwiejszego dostępu do tych danych, ale interfejs nie oferuje możliwości uzyskania całego adresu URL za pomocą jednego wywołania. Musisz go zbudować ręcznie:

public static String makeUrl(HttpServletRequest request)
{
    return request.getRequestURL().toString() + "?" + request.getQueryString();
}

Nie wiem, jak to zrobić z jakimikolwiek urządzeniami Spring MVC.

Jeśli chcesz uzyskać dostęp do bieżącego żądania bez przekazywania go wszędzie, będziesz musiał dodać odbiornik w web.xml:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

Następnie użyj tego, aby uzyskać żądanie powiązane z bieżącym wątkiem:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Daff
źródło
Ok, to jest podobne podejście do tego, co zrobiłem do tej pory. Ale szukam sposobu, aby to zrobić bez faktycznego używania HttpServletRequestobiektu. Dzieje się tak, ponieważ używam kilku klas / metod pomocniczych i nie chcę za każdym razem przekazywać obiektu żądania.
Koraktor
Wiem, co masz na myśli, i dodałem informacje potrzebne do uzyskania dostępu do bieżącego żądania bez przekazywania go.
Daff
Dzięki za przypomnienie o słuchaczu. Wciąż jestem nowy w Spring (i ogólnie w tworzeniu stron internetowych w Javie). Używam teraz Twojego kodu w połączeniu z Spring Security UrlUtils. Działa jak marzenie.
Koraktor
W moim przypadku podaje powiązaną ścieżkę widoku zamiast adresu URL przeglądania. Masz jakiś pomysł na ten temat?
Md. Shougat Hossain,
Bez użycia HttpServletRequest ... w metodach kontrolera Spring Boot nie otrzymujemy tego jako parametru ... wtedy druga odpowiedź statycznego wywołania wygląda dobrze ServletUriComponentsBuilder.fromCurrentRequest (). ToUriString ()
msanjay
77

Zamiast używać RequestContextHolderbezpośrednio, możesz również użyć ServletUriComponentsBuilderi jego metod statycznych:

  • ServletUriComponentsBuilder.fromCurrentContextPath()
  • ServletUriComponentsBuilder.fromCurrentServletMapping()
  • ServletUriComponentsBuilder.fromCurrentRequestUri()
  • ServletUriComponentsBuilder.fromCurrentRequest()

Używają RequestContextHolderpod maską, ale zapewniają dodatkową elastyczność przy tworzeniu nowych adresów URL przy użyciu możliwości UriComponentsBuilder.

Przykład:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
źródło
@ m4rtin Odpowiedziałem na własne pytanie i nie chciałem przypisywać uznania osobie, która początkowo pomogła mi rozwiązać mój problem.
Koraktor
2
Również dobre na wiosnę 5. Udało mi się uzyskać adres URL wewnątrz ConstraintValidatorz ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter
17

Klasa URI języka Java może Ci w tym pomóc:

public static String getCurrentUrl(HttpServletRequest request){
    URL url = new URL(request.getRequestURL().toString());
    String host  = url.getHost();
    String userInfo = url.getUserInfo();
    String scheme = url.getProtocol();
    String port = url.getPort();
    String path = request.getAttribute("javax.servlet.forward.request_uri");
    String query = request.getAttribute("javax.servlet.forward.query_string");

    URI uri = new URI(scheme,userInfo,host,port,path,query,null)
    return uri.toString();
}
Reed Grey
źródło
podaje tylko nazwę hosta
vivex
8

w pliku jsp:

request.getAttribute("javax.servlet.forward.request_uri")
andy
źródło
3

Możesz także dodać UriComponentsBuilderdo podpisu metody metody kontrolera. Spring wstrzyknie instancję konstruktora utworzoną na podstawie bieżącego żądania.

@GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
    URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
            .replacePath(null)
            .replaceQuery(null)
            .pathSegment("some", "new", "path")
            .build().toUri();
  //...
}

Korzystając z konstruktora, możesz bezpośrednio rozpocząć tworzenie identyfikatorów URI na podstawie bieżącego żądania, np. Modyfikować segmenty ścieżki.

Zobacz także UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
źródło
Należy zauważyć, że wstrzyknięty UriComponentsBuildernie zawiera ścieżki ani parametrów zapytania żądania. Jeśli potrzebujesz dostępu do nich, użyj ServletUriComponentsBuilder.fromCurrentRequest()lub wstrzyknij wystąpienie HttpServletRequesti użyjServletUriComponentsBuilder.fromRequest(request)
Martin Devillers,
-1

Jeśli potrzebujesz adresu URL do nazwy hosta, a nie ścieżki, użyj Common Lib Apache StringUtiliz adresu URL wyodrębnij podciąg do trzeciego indexOf /.

public static String getURL(HttpServletRequest request){
   String fullURL = request.getRequestURL().toString();
   return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3)); 
}

Przykład: Jeśli fullURL to https://example.com/path/after/url/to Output will be https://example.com

Sahil Chhabra
źródło