¿Cuál es la mejor manera de obtener la URL actual en Spring MVC?

95

Me gustaría crear URL basadas en la URL utilizada por el cliente para la solicitud activa. ¿Hay algo más inteligente que tomar el HttpServletRequestobjeto actual y sus getParameter...()métodos para reconstruir la URL completa, incluidos (y solo) sus parámetros GET?

Aclaración: Si es posible, quiero renunciar a usar un HttpServletRequestobjeto.

Koraktor
fuente

Respuestas:

111

Bueno, hay dos métodos para acceder a estos datos más fácilmente, pero la interfaz no ofrece la posibilidad de obtener la URL completa con una sola llamada. Tienes que construirlo manualmente:

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

No conozco una forma de hacer esto con ninguna instalación de Spring MVC.

Si desea acceder a la Solicitud actual sin pasarla a todas partes, tendrá que agregar un oyente en web.xml:

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

Y luego use esto para obtener la solicitud vinculada al hilo actual:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Narciso
fuente
Ok, este es un enfoque similar al que he hecho hasta ahora. Pero estoy buscando una forma de hacer esto sin usar el HttpServletRequestobjeto. Esto se debe a que estoy usando varias clases / métodos auxiliares y no quiero pasar el objeto de solicitud cada vez.
Koraktor
Ok, sé lo que quieres decir y agregué la información que necesitas para acceder a la solicitud actual sin pasarla.
Daff
Gracias por el recordatorio sobre el oyente. Todavía soy nuevo en Spring (y en el desarrollo web Java en general). Ahora estoy usando su código en combinación con Spring Security UrlUtils. Funciona de maravilla.
Koraktor
En mi caso, proporciona la ruta de vista relacionada en lugar de navegar por la URL. ¿Alguna idea sobre esto?
Md. Shougat Hossain
76

En lugar de usarlo RequestContextHolderdirectamente, también puede usar ServletUriComponentsBuildery sus métodos estáticos:

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

Se usan RequestContextHolderbajo el capó, pero brindan flexibilidad adicional para crear nuevas URL utilizando las capacidades de UriComponentsBuilder.

Ejemplo:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
fuente
@ m4rtin Respondí mi propia pregunta y no quería atribuirme el mérito de quien inicialmente me ayudó a resolver mi problema.
Koraktor
2
También es bueno para Spring 5. Me las arreglé para obtener la URL dentro de un ConstraintValidatorarchivo ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter
16

La clase URI de Java puede ayudarte con esto:

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
fuente
está dando solo el nombre de host
vivex
8

en el archivo jsp:

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

También puede agregar UriComponentsBuildera la firma del método de su método de controlador. Spring inyectará una instancia del constructor creado a partir de la solicitud actual.

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

Con el constructor, puede comenzar a crear URI directamente en función de la solicitud actual, por ejemplo, modificar segmentos de ruta.

Consulte también UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
fuente
Tenga en cuenta que el inyectado UriComponentsBuilderno incluye la ruta ni los parámetros de consulta de la solicitud. Si necesita acceder a ellos, use ServletUriComponentsBuilder.fromCurrentRequest()o inyecte una instancia de HttpServletRequesty useServletUriComponentsBuilder.fromRequest(request)
Martin Devillers
-1

Si necesita la URL hasta el nombre de host y no la ruta, use la biblioteca común de Apache StringUtil, y desde la URL extraiga la subcadena hasta el tercer índice de /.

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

Ejemplo: si fullURL es https://example.com/path/after/url/, la salida será https://example.com

Sahil Chhabra
fuente