Como obter o URI da solicitação sem o caminho do contexto?

127

O método request.getRequestURI () retorna URI com o caminho do contexto.

Por exemplo, se o URL base de uma aplicação é http://localhost:8080/myapp/(ou seja, o caminho do contexto é myapp ), e eu chamo request.getRequestURI()para http://localhost:8080/myapp/secure/users, ele irá retornar /myapp/secure/users.

Existe alguma maneira de obter apenas essa parte /secure/users, ou seja, o URI sem caminho de contexto?

artesão
fonte

Respostas:

158

Se você estiver dentro de um servlet de contoller frontal mapeado em um padrão de prefixo, poderá usar HttpServletRequest#getPathInfo().

String pathInfo = request.getPathInfo();
// ...

Supondo que o servlet no seu exemplo esteja mapeado /secure, isso retornará /usersas informações de interesse único dentro de um servlet de controlador frontal típico.

Se, no entanto, o servlet estiver mapeado em um padrão de sufixo (seus exemplos de URL não indicam que esse é o caso), ou quando você estiver realmente dentro de um filtro (quando o servlet a ser chamado ainda não estiver necessariamente determinado ainda, então getPathInfo()pode retornar null), então sua melhor aposta é substring o URI da solicitação com base no comprimento do caminho de contexto usando o Stringmétodo usual :

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...
BalusC
fonte
Existe uma razão para usar isso em vez de getServletPath()? Estou escrevendo um filtro e notei que getPathInfo()retorna null, mas getServletPath()retorna o caminho menos o contexto (adequado para passar para o distribuidor de solicitações).
Jason C
@JasonC: Como respondido, getPathInfo()retorna nulo se o servlet do controlador frontal não estiver mapeado em um padrão de prefixo.
BalusC
Sim. Eu quis dizer: existe uma razão pela qual você prefere getPathInfo sobre getServletPath? Muitas das outras respostas pontuadas aqui também não usam getServletPath, que é o que está me deixando desconfiado e por que estou me perguntando. Estou trabalhando em um projeto de servlet e estou tentando aprimorar minhas habilidades.
Jason C
1
@JasonC: o caminho do servlet está sujeito a alterações quando você possui uma estrutura MVC baseada em servlet instalada como JSF ou Spring MVC. Em seguida, ele representará o caminho interno da estrutura MVC (por exemplo, em /foo.xhtmlvez de /foo.jsf) e não o URI real da solicitação (aquele que o usuário final veria na barra de endereços do navegador). O caminho do servlet original é, nesse caso, no entanto resolvível como atributo de solicitação com chave RequestDispatcher.FORWARD_SERVLET_PATH. De qualquer forma, a pergunta solicita explicitamente o URI da solicitação (como na barra de endereços do navegador), portanto a resposta é baseada nisso.
BalusC
74
request.getRequestURI().substring(request.getContextPath().length())
fforw
fonte
Impressionante! Isto é exatamente o que eu estava procurando.
artesão
4
+1 Acho que essa é uma resposta melhor do que getPathInfo devido ao fato de que getPathInfo pode ser nulo e outras esquisitices. Vários códigos Spring obtêm o getContextPath e o removem do URI, como você fez em vez do getPathInfo.
Adam Gent
32

Com o Spring, você pode:

String path = new UrlPathHelper().getPathWithinApplication(request);
James
fonte
1
Claro que não faria sentido manter uma instância do UrlPathHelper por exemplo, como uma variável membro da classe ...
James
Como podemos obter o URL de mapeamento de solicitação real?
Guie
14

Às vezes, getPathInfo () retorna nulo. Na documentação HttpServletRequest

Este método retorna nulo se não houver informações adicionais sobre o caminho.

Preciso obter o caminho para o arquivo sem o caminho de contexto no Filter e getPathInfo () me retorna nulo. Então, eu uso outro método: httpRequest.getServletPath ()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}
lukastymo
fonte
8

Se você usar request.getPathInfo () dentro de um filtro, sempre parecerá nulo (pelo menos com o jetty).

Este erro + resposta concisa alude ao problema que penso:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

Suspeito que esteja relacionado ao fato de os filtros serem executados antes do servlet receber a solicitação. Pode ser um bug do contêiner ou comportamento esperado que não consegui identificar.

O contextPath está disponível, portanto, a solução fforws funciona mesmo em filtros. Não gosto de fazer isso manualmente, mas a implementação está interrompida ou

thetoolman
fonte
5

Uma maneira de fazer isso é repousar o caminho de contexto da servelet do URI da solicitação.

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

Leia aqui .

PeterMmm
fonte
-1

Pode ser que você possa usar o método split para eliminar o '/ myapp', por exemplo:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
fonte
3
Isso causará problemas se eu implantar meu aplicativo como raiz e seu URL base se tornar localhost: 8080 . Nesse caso, request.getRequestURI () retornaria "/ secure / user" e seu método split causará problemas aqui. O código não deve depender da implantação.
artesão