Qual é a melhor maneira de obter a URL atual no Spring MVC?

95

Eu gostaria de criar URLs com base no URL usado pelo cliente para a solicitação ativa. Existe algo mais inteligente do que pegar o HttpServletRequestobjeto atual e seus getParameter...()métodos para reconstruir a URL completa incluindo (e apenas) seus parâmetros GET.

Esclarecimento: Se possível, desejo desistir de usar um HttpServletRequestobjeto.

Koraktor
fonte

Respostas:

111

Bem, existem dois métodos para acessar esses dados mais facilmente, mas a interface não oferece a possibilidade de obter a URL inteira com uma chamada. Você deve construí-lo manualmente:

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

Não sei como fazer isso com as instalações do Spring MVC.

Se você deseja acessar a solicitação atual sem passá-la em todos os lugares, você terá que adicionar um ouvinte no web.xml:

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

Em seguida, use isso para vincular a solicitação ao Thread atual:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Daff
fonte
Ok, esta é uma abordagem semelhante ao que fiz até agora. Mas estou procurando uma maneira de fazer isso sem realmente usar o HttpServletRequestobjeto. Isso ocorre porque estou usando várias classes / métodos auxiliares e não quero passar o objeto de solicitação todas as vezes.
Koraktor,
Ok, eu sei o que você quer dizer e adicionei as informações de que você precisa para acessar a solicitação atual sem repassá-la.
Daff,
Obrigado pelo lembrete sobre o ouvinte. Ainda sou novo no Spring (e no desenvolvimento web em Java em geral). Agora estou usando seu código em combinação com o do Spring Security UrlUtils. Funciona como um encanto.
Koraktor,
No meu caso, ele fornece o caminho de visualização relacionado em vez do URL de navegação. Alguma ideia sobre isso?
Md. Shougat Hossain
76

Em vez de usar RequestContextHolderdiretamente, você também pode usar ServletUriComponentsBuildere seus métodos estáticos:

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

Eles usam RequestContextHoldernos bastidores, mas fornecem flexibilidade adicional para construir novos URLs usando os recursos do UriComponentsBuilder.

Exemplo:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
fonte
@ m4rtin Eu respondi minha própria pergunta e não queria levar o crédito por quem inicialmente me ajudou a resolver meu problema.
Koraktor
2
Também bom para o Spring 5. Consegui obter a URL dentro de um ConstraintValidatorcom ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter
16

A classe URI do Java pode ajudá-lo nisso:

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 Gray
fonte
está fornecendo apenas o nome do host
vivex
8

no arquivo jsp:

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

Você também pode adicionar um UriComponentsBuilderà assinatura do método do seu método de controlador. O Spring injetará uma instância do construtor criado a partir da solicitação atual.

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

Usando o construtor, você pode começar a criar URIs diretamente com base na solicitação atual, por exemplo, modificar segmentos de caminho.

Veja também UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
fonte
Observe que o injetado UriComponentsBuildernão inclui o caminho e os parâmetros de consulta da solicitação. Se você precisar acessá-los, use ServletUriComponentsBuilder.fromCurrentRequest()ou injete uma instância de HttpServletRequeste useServletUriComponentsBuilder.fromRequest(request)
Martin Devillers
-1

Se você precisar da URL até o nome do host e não o caminho, use a biblioteca comum do Apache StringUtil, e da URL extraia a substring até o terceiro indexOf /.

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

Exemplo: se fullURL for https://example.com/path/after/url/, a saída será https://example.com

Sahil Chhabra
fonte