¿Cuál es la diferencia entre los métodos getRequestURI y getPathInfo en HttpServletRequest?

143

Estoy haciendo un controlador frontal simple y muy ligero. Necesito hacer coincidir las rutas de solicitud con diferentes controladores (acciones) para elegir la correcta.

En mi máquina local HttpServletRequest.getPathInfo()y HttpServletRequest.getRequestURI()devolver los mismos resultados. Pero no estoy seguro de qué devolverán en el entorno de producción.

Entonces, ¿cuál es la diferencia entre estos métodos y qué debo elegir?

romano
fuente
1
Puede encontrar esta respuesta útil también.
BalusC
@BalusC: gracias, ya he estado usando algunos consejos de esa respuesta.
Romano
Esto explica la diferencia con un buen diagrama: agiletribe.wordpress.com/2016/02/23/…
AgilePro

Respuestas:

77

getPathInfo()proporciona la información de ruta adicional después del URI, que se utiliza para acceder a su Servlet, mientras que getRequestURI()proporciona el URI completo.

Pensé que serían diferentes, dado que un Servlet debe configurarse con su propio patrón de URI en primer lugar; Creo que nunca he servido un Servlet desde la raíz (/).

Por ejemplo, si el Servlet 'Foo' está asignado a URI '/ foo', entonces habría pensado que el URI:

/foo/path/to/resource

Daría como resultado:

RequestURI = /foo/path/to/resource

y

PathInfo = /path/to/resource
trojanfoe
fuente
20
Vale la pena mencionar sobre el comportamiento de decodificación. getRequestURI () no decodifica la cadena. Donde getPathInfo () decodifica.
Kavindu Dodanduwa
1
En algunos casos getRequestURI()me da la cadena "/foo/path/to/resource"como se esperaba, pero getPathInfo()para el mismo HttpServletRequestobjeto me da null. ¿Qué sucede? EDITAR: se responde a continuación por el usuario "30thh".
anddero
460

Pondré una pequeña tabla de comparación aquí (solo para tenerla en alguna parte):

Servlet se asigna como /test%3F/*y la aplicación se implementa en /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

En el ejemplo anterior, el servidor se ejecuta en localhost:8480y el nombre 30thh.locse puso en el hostsarchivo del sistema operativo .

Comentarios

  • "+" se maneja como espacio solo en la cadena de consulta

  • El ancla "#a" no se transfiere al servidor. Solo el navegador puede trabajar con él.

  • Si el url-patternmapeo en el servlet no termina con *(por ejemplo /testo *.jsp), getPathInfo()regresa null.

Si se usa Spring MVC

  • El método getPathInfo()vuelve null.

  • El método getServletPath()devuelve la parte entre la ruta de contexto y la ID de sesión. En el ejemplo anterior, el valor sería/test?/a?+b

  • Tenga cuidado con las partes codificadas con URL de @RequestMappingy @RequestParamen Spring. Tiene errores (versión actual 3.2.4) y generalmente no funciona como se esperaba .

30thh
fuente
20
Estoy imprimiendo tu respuesta y la pongo como póster en nuestra oficina. ¡Así de útil es!
Ibrahim Arief
2
If the url-pattern in the servlet mapping does not end with * (for example /test or *.jsp), getPathInfo() returns null.brillante.
Boris Treukhov
1
Creo en ambos getRequestURI()y getRequestURL()debería devolver jsessionid no decodificado, en este caso S%3F+ID. Al menos lo hace en Tomcat / 8.5.6.
Gediminas Rimsa
30

Analicemos la URL completa que un cliente escribiría en su barra de direcciones para llegar a su servlet:

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

Las partes son:

  1. esquema: http
  2. nombre de host: www.example.com
  3. Puerto: 80
  4. ruta de contexto: awesome-application
  5. ruta de servlet: path/to/servlet
  6. información de ruta: path/info
  7. consulta: a=1&b=2
  8. fragmento: boo

El URI de solicitud (devuelto por getRequestURI ) corresponde a las partes 4, 5 y 6.

(por cierto, aunque no esté solicitando esto, el método getRequestURL le proporcionará las partes 1, 2, 3, 4, 5 y 6).

Ahora:

  • la parte 4 (la ruta de contexto) se usa para seleccionar su aplicación particular de muchas otras aplicaciones que pueden estar ejecutándose en el servidor
  • la parte 5 (la ruta del servlet) se usa para seleccionar un servlet particular de muchos otros servlets que se pueden agrupar en la WAR de su aplicación
  • la parte 6 (la información de ruta) es interpretada por la lógica de su servlet (por ejemplo, puede apuntar a algún recurso controlado por su servlet).
  • la parte 7 (la consulta) también está disponible para su servlet usando getQueryString
  • la parte 8 (el fragmento) ni siquiera se envía al servidor y es relevante y conocida solo por el cliente

Siempre se cumple lo siguiente (excepto las diferencias de codificación de URL):

requestURI = contextPath + servletPath + pathInfo

El siguiente ejemplo de la especificación Servlet 3.0 es muy útil:


Nota: la imagen sigue, no tengo tiempo para recrear en HTML:

ingrese la descripción de la imagen aquí

Marcus Junius Brutus
fuente
16

Considere la siguiente configuración de servlet:

   <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>

Ahora, cuando llego a la URL http://localhost:8084/JSPTemp1/NewServlet/jhi, invocará NewServletcomo está mapeado con el patrón descrito anteriormente.

Aquí:

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

Tenemos esos:

  • getPathInfo()

    devuelve
    una Cadena, decodificada por el contenedor web, que especifica la información de ruta adicional que viene después de la ruta del servlet pero antes de la cadena de consulta en la URL de solicitud; o nulo si la URL no tiene ninguna información de ruta adicional

  • getRequestURI()

    devuelve
    una cadena que contiene la parte de la URL desde el nombre del protocolo hasta la cadena de consulta

Jigar Joshi
fuente