Qual é a diferença entre os métodos getRequestURI e getPathInfo no HttpServletRequest?

143

Estou criando um controlador frontal simples e muito leve. Preciso corresponder caminhos de solicitação a diferentes manipuladores (ações) para escolher o caminho correto.

Na minha máquina local HttpServletRequest.getPathInfo()e HttpServletRequest.getRequestURI()retorne os mesmos resultados. Mas não tenho certeza do que eles retornarão no ambiente de produção.

Então, qual é a diferença entre esses métodos e o que devo escolher?

romano
fonte
1
Você também pode achar útil essa resposta .
BalusC
@ BalusC: obrigado, eu já estou usando algumas dicas dessa resposta.
Roman
Isso explica a diferença com um bom diagrama: agiletribe.wordpress.com/2016/02/23/…
AgilePro 01/08/19

Respostas:

77

getPathInfo()fornece as informações adicionais do caminho após o URI, usado para acessar o seu Servlet, enquanto as getRequestURI()fornece o URI completo.

Eu pensaria que eles seriam diferentes, dado que um Servlet deve ser configurado com seu próprio padrão de URI; Acho que nunca servi um Servlet a partir da raiz (/).

Por exemplo, se o Servlet 'Foo' estiver mapeado para o URI '/ foo', eu teria pensado que o URI:

/foo/path/to/resource

Resultaria em:

RequestURI = /foo/path/to/resource

e

PathInfo = /path/to/resource
trojanfoe
fonte
20
vale a pena mencionar sobre o comportamento de decodificação. getRequestURI () não decodifica a sequência. Onde getPathInfo () decodifica.
Kavindu Dodanduwa
1
Em alguns casos, getRequestURI()me dá a string "/foo/path/to/resource"conforme o esperado, mas getPathInfo()para o mesmo HttpServletRequestobjeto me dá null. O que anda acontecendo no mundo? EDIT: É respondido abaixo pelo usuário "30thh".
anddero
460

Vou colocar uma pequena tabela de comparação aqui (apenas para tê-la em algum lugar):

O servlet é mapeado como /test%3F/*e o aplicativo é implementado em /app.

http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S%3F+ID?p+1=c+d&p+2=e+f#a

Method              URL-Decoded Result           
----------------------------------------------------
getContextPath()        no      /app
getLocalAddr()                  127.0.0.1
getLocalName()                  30thh.loc
getLocalPort()                  8480
getMethod()                     GET
getPathInfo()           yes     /a?+b
getProtocol()                   HTTP/1.1
getQueryString()        no      p+1=c+d&p+2=e+f
getRequestedSessionId() no      S%3F+ID
getRequestURI()         no      /app/test%3F/a%3F+b;jsessionid=S+ID
getRequestURL()         no      http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S+ID
getScheme()                     http
getServerName()                 30thh.loc
getServerPort()                 8480
getServletPath()        yes     /test?
getParameterNames()     yes     [p 2, p 1]
getParameter("p 1")     yes     c d

No exemplo acima, o servidor está sendo executado no localhost:8480e o nome 30thh.locfoi colocado no hostsarquivo do SO .

Comentários

  • "+" é tratado como espaço apenas na string de consulta

  • A âncora "#a" não é transferida para o servidor. Somente o navegador pode trabalhar com ele.

  • Se o url-patternmapeamento no servlet não terminar com *(por exemplo /testou *.jsp), getPathInfo()retornará null.

Se o Spring MVC for usado

  • Método getPathInfo()retorna null.

  • O método getServletPath()retorna a parte entre o caminho do contexto e o ID da sessão. No exemplo acima, o valor seria/test?/a?+b

  • Cuidado com as partes codificadas por URL do @RequestMappinge @RequestParamno Spring. É buggy (versão atual 3.2.4) e geralmente não está funcionando como esperado .

30ª
fonte
20
Estou imprimindo sua resposta e colocando-a como um cartaz em nosso escritório. É assim que é útil!
Ibrahim Arief
2
If the url-pattern in the servlet mapping does not end with * (for example /test or *.jsp), getPathInfo() returns null.brilhante.
Boris Treukhov 27/10/16
1
Eu acredito em ambos getRequestURI()e getRequestURL()devo retornar jsessionid não decodificado, neste caso S%3F+ID. Pelo menos no Tomcat / 8.5.6.
Gediminas Rimsa
29

Vamos detalhar o URL completo que um cliente digitaria na barra de endereço para acessar seu servlet:

http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo

As peças são:

  1. esquema: http
  2. nome de anfitrião: www.example.com
  3. porta: 80
  4. caminho de contexto: awesome-application
  5. caminho do servlet: path/to/servlet
  6. informações do caminho: path/info
  7. inquerir: a=1&b=2
  8. fragmento: boo

O URI da solicitação (retornado por getRequestURI ) corresponde às partes 4, 5 e 6.

(aliás, mesmo que você não esteja pedindo isso, o método getRequestURL fornecerá as partes 1, 2, 3, 4, 5 e 6).

Agora:

  • a parte 4 (o caminho do contexto) é usada para selecionar seu aplicativo específico dentre muitos outros aplicativos que podem estar em execução no servidor
  • A parte 5 (o caminho do servlet) é usada para selecionar um servlet específico dentre muitos outros servlets que podem ser agrupados no WAR do aplicativo
  • a parte 6 (as informações do caminho) é interpretada pela lógica do seu servlet (por exemplo, pode apontar para algum recurso controlado por seu servlet).
  • A parte 7 (a consulta) também é disponibilizada para o seu servlet usando getQueryString
  • a parte 8 (o fragmento) nem é enviada ao servidor e é relevante e conhecida apenas pelo cliente

O seguinte sempre é válido (exceto para diferenças de codificação de URL):

requestURI = contextPath + servletPath + pathInfo

O exemplo a seguir da especificação Servlet 3.0 é muito útil:


Nota: a imagem a seguir, não tenho tempo para recriar em HTML:

insira a descrição da imagem aqui

Marcus Junius Brutus
fonte
16

Considere o seguinte servlet conf:

   <servlet>
        <servlet-name>NewServlet</servlet-name>
        <servlet-class>NewServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>NewServlet</servlet-name>
        <url-pattern>/NewServlet/*</url-pattern>
    </servlet-mapping>

Agora, quando eu clicar no URL http://localhost:8084/JSPTemp1/NewServlet/jhi, ele será chamado NewServletconforme é mapeado com o padrão descrito acima.

Aqui:

getRequestURI() =  /JSPTemp1/NewServlet/jhi
getPathInfo() = /jhi

Nós temos os seguintes:

  • getPathInfo()

    retorna
    uma String, decodificada pelo contêiner da Web, especificando informações adicionais sobre o caminho que vêm após o caminho do servlet, mas antes da string de consulta no URL da solicitação; ou null se o URL não tiver nenhuma informação de caminho extra

  • getRequestURI()

    retorna
    uma String contendo a parte da URL do nome do protocolo até a string de consulta

Jigar Joshi
fonte