¿Cómo obtener el URI de solicitud sin ruta de contexto?

127

El método request.getRequestURI () devuelve URI con la ruta de contexto.

Por ejemplo, si la URL base de una aplicación es http://localhost:8080/myapp/(es decir, la ruta de contexto es miaplicacion ), y llamar request.getRequestURI()para http://localhost:8080/myapp/secure/users, devolverá /myapp/secure/users.

¿Hay alguna manera de que podamos obtener solo esta parte /secure/users, es decir, el URI sin ruta de contexto?

artesano
fuente

Respuestas:

158

Si está dentro de un servlet de control frontal que está mapeado en un patrón de prefijo, entonces puede usarlo HttpServletRequest#getPathInfo().

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

Suponiendo que el servlet en su ejemplo está mapeado /secure, esto devolverá lo /usersque sería la información de interés exclusivo dentro de un servlet de controlador frontal típico.

Sin embargo, si el servlet está mapeado en un patrón de sufijo (sus ejemplos de URL sin embargo no indican que este sea el caso), o cuando está realmente dentro de un filtro (cuando el servlet a invocar aún no está necesariamente determinado, entonces getPathInfo()podría volver null), entonces su mejor opción es substraer el URI de solicitud usted mismo en función de la longitud de la ruta de contexto utilizando el Stringmétodo habitual :

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...
BalusC
fuente
¿Hay alguna razón para usar esto en lugar de getServletPath()? Estoy escribiendo un filtro y noté que getPathInfo()devuelve null, pero getServletPath()devuelve la ruta menos el contexto (adecuado para pasar al despachador de solicitudes).
Jason C
@JasonC: como se respondió, getPathInfo()devuelve nulo si el servlet del controlador frontal no está asignado en un patrón de prefijo.
BalusC
Si. Quiero decir: ¿hay alguna razón por la que prefieras getPathInfo sobre getServletPath? Muchas de las otras respuestas mejor calificadas aquí tampoco usan getServletPath, que es lo que me hace sospechar de eso y por qué me pregunto. Tengo un proyecto de servlet en el que estoy trabajando y estoy tratando de pulir mis habilidades.
Jason C
1
@JasonC: la ruta del servlet está sujeta a cambios cuando tiene instalado un marco MVC basado en servlet como JSF o Spring MVC. Luego representará la ruta interna del marco MVC (por ejemplo, en /foo.xhtmllugar de /foo.jsf) y no el URI de solicitud real (el que el usuario final vería en la barra de direcciones del navegador). La ruta del servlet original es en tal caso, sin embargo, resoluble como atributo de solicitud con clave RequestDispatcher.FORWARD_SERVLET_PATH. De cualquier manera, la pregunta solicita explícitamente el URI de solicitud (como en la barra de direcciones del navegador), por lo que la respuesta se basa en eso.
BalusC
74
request.getRequestURI().substring(request.getContextPath().length())
adelante
fuente
¡Increíble! Esto es exactamente lo que estaba buscando.
artesano
44
+1 Creo que esta es una mejor respuesta que getPathInfo debido al hecho de que getPathInfo puede ser nulo y otras rarezas. Varios códigos Spring obtienen getContextPath y lo eliminan del URI tal como lo hizo en lugar de getPathInfo.
Adam Gent
32

Con Spring puedes hacer:

String path = new UrlPathHelper().getPathWithinApplication(request);
James
fuente
1
Por supuesto, tendría sentido mantener una instancia de UrlPathHelper, por ejemplo, como una variable de miembro de clase ...
James
¿Cómo podemos obtener la URL de mapeo de solicitud real?
Guíe
14

getPathInfo () a veces devuelve nulo. En la documentación HttpServletRequest

Este método devuelve nulo si no había información de ruta adicional.

Necesito obtener la ruta al archivo sin ruta de contexto en Filter y getPathInfo () me devuelve nulo. Entonces uso otro 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
fuente
8

Si usa request.getPathInfo () dentro de un filtro, siempre parece ser nulo (al menos con jetty).

Este breve error inválido + respuesta alude al problema, creo:

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

Sospecho que está relacionado con el hecho de que los filtros se ejecutan antes de que el servlet reciba la solicitud. Puede ser un error de contenedor o un comportamiento esperado que no he podido identificar.

Sin embargo, contextPath está disponible, por lo que la solución fforws funciona incluso en filtros. No me gusta tener que hacerlo a mano, pero la implementación está rota o

thetoolman
fuente
5

Una forma de hacerlo es descansar la ruta de contexto del servidor desde el URI de la solicitud.

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

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

Lea aquí .

PeterMmm
fuente
-1

Puede ser que pueda usar el método de división para eliminar '/ myapp', por ejemplo:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
fuente
3
Esto causará problemas si implemento mi aplicación como root y su URL base se convierte en localhost: 8080 . En este caso, request.getRequestURI () devolvería "/ secure / user" y su método de división causará problemas aquí. El código no debe depender de la implementación.
artesano