¿Cómo usar un filtro de servlet en Java para cambiar una url de solicitud de servlet entrante?

186

¿Cómo puedo usar un filtro de servlet para cambiar una url de solicitud de servlet entrante de

http://nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123

a

http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123

?


Actualización : de acuerdo con los pasos de BalusC a continuación, se me ocurrió el siguiente código:

public class UrlRewriteFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        //
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        String requestURI = request.getRequestURI();

        if (requestURI.startsWith("/Check_License/Dir_My_App/")) {
            String toReplace = requestURI.substring(requestURI.indexOf("/Dir_My_App"), requestURI.lastIndexOf("/") + 1);
            String newURI = requestURI.replace(toReplace, "?Contact_Id=");
            req.getRequestDispatcher(newURI).forward(req, res);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {
        //
    }
}

La entrada relevante en se web.xmlve así:

<filter>
    <filter-name>urlRewriteFilter</filter-name>
    <filter-class>com.example.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>urlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Intenté la redirección del lado del servidor y del lado del cliente con los resultados esperados. Funcionó, gracias BalusC!

Franco
fuente
Pregunta relacionada: stackoverflow.com/questions/2723829/…
BalusC
¿Qué versión de la especificación del servlet estás usando? Cómo reenviar solicitudes cambia con las diferentes versiones.
Romain Hippeau
Ver esta publicación también tiene un filtro que hace lo que quieres
Romain Hippeau
Tenga en cuenta que si su URL original contiene parámetros, es decir, nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123 ? ** param1 = A & param2 = B **, estos parámetros también se enviarán al siguiente servlet / jsp. No encontré una manera de deshacerme o reemplazar los parámetros originales (solo usando HttpServletRequestWrapper). ¿Alguna idea? .. Actualización: parece que http://ocpsoft.org/opensource/how-to-safely-add-modify-servlet-request-parameter-values/ soluciona este problema.
Lopotun
Gracias, estaba buscando un ejemplo de reescritura de URL y cifrado.
Aditya Yada

Respuestas:

281
  1. Poner en práctica javax.servlet.Filter.
  2. En doFilter()método, emite el entrante ServletRequesta HttpServletRequest.
  3. Use HttpServletRequest#getRequestURI()para agarrar el camino.
  4. Utilice sencillos java.lang.Stringmétodos como substring(), split(), concat()y así sucesivamente para extraer la parte de interés y componer la nueva ruta.
  5. Utilice uno ServletRequest#getRequestDispatcher()y luego RequestDispatcher#forward()enviar la petición / respuesta a la nueva URL (redirección del lado del servidor, no se refleja en la barra de direcciones del navegador), o emitir el entrante ServletResponsea HttpServletResponsey luego HttpServletResponse#sendRedirect()volver a dirigir la respuesta a la nueva URL (redirección del lado del cliente, que se refleja en barra de direcciones del navegador).
  6. Registre el filtro en web.xmluna url-patternde /*o /Check_License/*, dependiendo de la ruta de contexto, o si ya está en Servlet 3.0, use la @WebFilteranotación para eso.

No olvide agregar un cheque en el código si la URL necesita ser cambiada y si no , simplemente llame FilterChain#doFilter(), de lo contrario se llamará a sí mismo en un bucle infinito.

Alternativamente, también puede usar una API de terceros existente para hacer todo el trabajo por usted, como UrlRewriteFilter de Tuckey, que se puede configurar de la misma manera que lo haría con Apache mod_rewrite.

BalusC
fuente
1
¿Algún código de muestra doFilter () en algún lugar que haga lo anterior? Gracias.
Frank
20
¿En qué paso estás exactamente pegado? Mi respuesta casi escribe el código en sí. ¿También notó que las referencias de código en azul son en realidad enlaces a Javadocs que describen el comportamiento de clase / método en detalle? De cualquier manera, puede encontrar aquí y aquí buenos tutoriales de JSP / Servlet, específicamente este sobre filtros.
BalusC
1
Supongo que es correcto, pero si el filtro es uno de los primeros en la cadena y RequestDispatcher#forward()se ejecuta, el resto de los filtros no se ejecutarán. Entonces, ¿no será una mejor manera que hacerlo como un servlet?
lucasvc
2
@datakey: simplemente reorganice el orden o agregue <dispatcher>FORWARD</dispatcher>al mapeo de filtro.
BalusC
1
@ JimJim2000: simplemente reorganice el orden o agregue <dispatcher>FORWARD</dispatcher>al mapeo de filtro.
BalusC
21

Puede usar el filtro de reescritura de URL listo para usar con una regla como esta:

<rule>
  <from>^/Check_License/Dir_My_App/Dir_ABC/My_Obj_([0-9]+)$</from>
  <to>/Check_License?Contact_Id=My_Obj_$1</to>
</rule>

Consulte los ejemplos para más ... ejemplos.

Pascal Thivent
fuente
7

Un simple filtro JSF Url Prettyfier basado en los pasos de la respuesta de BalusC . El filtro reenvía todas las solicitudes que comienzan con la ruta / ui (suponiendo que tenga todos sus archivos xhtml almacenados allí) a la misma ruta, pero agregando el sufijo xhtml.

public class UrlPrettyfierFilter implements Filter {

    private static final String JSF_VIEW_ROOT_PATH = "/ui";

    private static final String JSF_VIEW_SUFFIX = ".xhtml";

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
        String requestURI = httpServletRequest.getRequestURI();
        //Only process the paths starting with /ui, so as other requests get unprocessed. 
        //You can register the filter itself for /ui/* only, too
        if (requestURI.startsWith(JSF_VIEW_ROOT_PATH) 
                && !requestURI.contains(JSF_VIEW_SUFFIX)) {
            request.getRequestDispatcher(requestURI.concat(JSF_VIEW_SUFFIX))
                .forward(request,response);
        } else {
            chain.doFilter(httpServletRequest, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}
Xtreme Biker
fuente