Quelle est la meilleure façon d'obtenir l'URL actuelle dans Spring MVC?

95

Je voudrais créer des URL basées sur l'URL utilisée par le client pour la demande active. Y a-t-il quelque chose de plus intelligent que de prendre l' HttpServletRequestobjet actuel et ses getParameter...()méthodes pour reconstruire l'URL complète, y compris (et seulement) ses paramètres GET.

Clarification: si possible, je souhaite renoncer à utiliser un HttpServletRequestobjet.

Koraktor
la source

Réponses:

111

Eh bien, il existe deux méthodes pour accéder plus facilement à ces données, mais l'interface n'offre pas la possibilité d'obtenir l'URL entière en un seul appel. Vous devez le construire manuellement:

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

Je ne sais pas comment faire cela avec les installations Spring MVC.

Si vous souhaitez accéder à la requête actuelle sans la passer partout, vous devrez ajouter un écouteur dans le fichier web.xml:

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

Et puis utilisez ceci pour obtenir la demande liée au thread actuel:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Daff
la source
Ok, c'est une approche similaire à ce que j'ai fait jusqu'à présent. Mais je cherche un moyen de faire cela sans utiliser réellement l' HttpServletRequestobjet. C'est parce que j'utilise plusieurs classes / méthodes d'assistance et que je ne veux pas passer l'objet de requête à chaque fois.
Koraktor
Ok, je sais ce que vous voulez dire et j'ai ajouté les informations dont vous avez besoin pour accéder à la demande actuelle sans la passer.
Daff le
Merci pour le rappel concernant l'auditeur. Je suis encore nouveau dans Spring (et dans le développement Web Java en général). J'utilise maintenant votre code en combinaison avec Spring Security UrlUtils. Fonctionne comme un charme.
Koraktor le
Dans mon cas, il donne le chemin de vue associé au lieu de l'URL de navigation. Une idée à ce sujet?
Md. Shougat Hossain
76

Au lieu d'utiliser RequestContextHolderdirectement, vous pouvez également utiliser ServletUriComponentsBuilderet ses méthodes statiques:

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

Ils utilisent RequestContextHoldersous le capot, mais offrent une flexibilité supplémentaire pour créer de nouvelles URL en utilisant les capacités de UriComponentsBuilder.

Exemple:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
la source
@ m4rtin J'ai répondu à ma propre question et je ne voulais pas m'attribuer le mérite de celui qui m'avait initialement aidé à résoudre mon problème.
Koraktor
2
Aussi bien pour Spring 5. J'ai réussi à obtenir l'URL dans un ConstraintValidatoravec ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter
16

La classe URI de Java peut vous aider à en sortir:

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();
}
Gris roseau
la source
son nom d'hôte seulement
vivex
8

dans le fichier jsp:

request.getAttribute("javax.servlet.forward.request_uri")
Andy
la source
3

Vous pouvez également ajouter un UriComponentsBuilderà la signature de méthode de votre méthode de contrôleur. Spring injectera une instance du générateur créée à partir de la requête actuelle.

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

En utilisant le générateur, vous pouvez directement commencer à créer des URI basés sur la demande actuelle, par exemple modifier les segments de chemin.

Voir aussi UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
la source
Notez que l'injecté UriComponentsBuildern'inclut pas le chemin et les paramètres de requête de la requête. Si vous avez besoin d'accéder à ceux-ci, utilisez ServletUriComponentsBuilder.fromCurrentRequest()ou injectez une instance de HttpServletRequestet utilisezServletUriComponentsBuilder.fromRequest(request)
Martin Devillers
-1

Si vous avez besoin de l'URL jusqu'au nom d'hôte et non du chemin, utilisez la bibliothèque commune d'Apache StringUtil, et à partir de l'URL, extrayez la sous-chaîne jusqu'au troisième indexOf /.

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

Exemple: si fullURL est https://example.com/path/after/url/alors Output sera https://example.com

Sahil Chhabra
la source