Como usar um filtro de servlet em Java para alterar um URL de solicitação de servlet de entrada?

186

Como posso usar um filtro de servlet para alterar um URL de solicitação de servlet de entrada

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

para

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

?


Atualização : de acordo com as etapas abaixo do BalusC, vim com o seguinte 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() {
        //
    }
}

A entrada relevante aparece web.xmlassim:

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

Tentei o redirecionamento do servidor e do cliente com os resultados esperados. Funcionou, obrigado BalusC!

Frank
fonte
Pergunta relacionada: stackoverflow.com/questions/2723829/…
BalusC
Qual versão da especificação do servlet você está usando? Como você encaminha as solicitações muda com as diferentes versões.
Romain Hippeau
Veja este post também tem um filtro que faz o que quiser
Romain Hippeau
Observe que se o seu URL original contiver parâmetros, como nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123 ? ** param1 = A & param2 = B **, esses parâmetros também serão encaminhados para o próximo servlet / jsp. Não encontrei uma maneira de me livrar ou substituir parâmetros originais (apenas usando HttpServletRequestWrapper). Alguma idéia? .. Atualização: parece que http://ocpsoft.org/opensource/how-to-safely-add-modify-servlet-request-parameter-values/ soluciona esse problema.
Lopotun 17/05
Obrigado, estava procurando um exemplo de reescrita e criptografia de URL.
Aditya Yada

Respostas:

281
  1. Implementar javax.servlet.Filter.
  2. No doFilter()método, transmita a entrada ServletRequestpara HttpServletRequest.
  3. Use HttpServletRequest#getRequestURI()para pegar o caminho.
  4. Use simples java.lang.Stringmétodos como substring(), split(), concat()e assim por diante para extrair a parte de interesse e compor o novo caminho.
  5. Use ServletRequest#getRequestDispatcher()e, em seguida, RequestDispatcher#forward()para encaminhar a solicitação / resposta para o novo URL (redirecionamento do servidor, não refletido na barra de endereços do navegador), ou converter a entrada ServletResponsepara HttpServletResponsee, em seguida, HttpServletResponse#sendRedirect()redirecionar a resposta para o novo URL (redirecionamento do cliente, refletido em barra de endereço do navegador).
  6. Registre o filtro em web.xmlum url-patternde /*ou /Check_License/*, dependendo do caminho do contexto, ou se você já estiver no Servlet 3.0, use a @WebFilteranotação para isso.

Não se esqueça de adicionar uma verificação no código se o URL precisar ser alterado e, caso contrário , basta chamar FilterChain#doFilter(), caso contrário ele se chamará em um loop infinito.

Como alternativa, você também pode usar uma API de terceiros existente para fazer todo o trabalho para você, como o UrlRewriteFilter da Tuckey, que pode ser configurado da mesma maneira que faria com o Apache mod_rewrite.

BalusC
fonte
1
Algum código de exemplo doFilter () em algum lugar que faça o acima? Obrigado.
27410 Frank
20
Em que etapa exatamente você está atrapalhando? Minha resposta quase escreve o próprio código. Você também notou que as referências de código em azul são na verdade links para Javadocs, que descrevem o comportamento da classe / método em detalhes? De qualquer forma, você pode encontrar aqui e aqui bons tutoriais de JSP / Servlet, especificamente este sobre filtros.
BalusC
1
Suponho que esteja correto, mas se o filtro for um dos primeiros da cadeia e RequestDispatcher#forward()for executado, o restante dos filtros não será executado. Então, não haverá uma maneira melhor do que fazer isso como um servlet?
Lucasvc
2
@ datakey: apenas reorganize a ordem ou adicione <dispatcher>FORWARD</dispatcher>ao mapeamento do filtro.
precisa saber é o seguinte
1
@ JimJim2000: apenas reorganize a ordem ou adicione <dispatcher>FORWARD</dispatcher>ao mapeamento do filtro.
BalusC
21

Você pode usar o filtro de reescrita de URL pronto para usar com uma regra 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>

Veja os exemplos para mais ... exemplos.

Pascal Thivent
fonte
7

Um simples filtro JSF Url Prettyfier baseado nas etapas da resposta do BalusC . O filtro encaminha todas as solicitações começando com o caminho / ui (supondo que você tenha todos os seus arquivos xhtml armazenados lá) para o mesmo caminho, mas adicionando o sufixo 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
fonte