Usando o SiteMesh com o requestDispatcher's Forward ()
Pergunta
Estou tentando integrar Sitemesh em um aplicativo herdado usando o TomCat 5 como meu contêiner. eu tenho um main.jsp
Que estou decorando com um decorador simples.
Dentro decorators.xml
, Acabei de definir um decorador:
<decorators defaultdir="/decorators">
<decorator name="layout-main" page="layout-main.jsp">
<pattern>/jsp/main.jsp</pattern>
</decorator>
</decorators>
Este decorador funciona se eu for manualmente para http://example.com/my-webapp/jsp/main.jsp
. No entanto, existem alguns lugares onde um servlet, em vez de redirecionar para um JSP, faz um frente:
getServletContext().getRequestDispatcher("/jsp/main.jsp").forward(request, response);
Isso significa que o URL permanece em algo como http://example.com/my-webapp/servlet/MyServlet
Em vez do arquivo JSP e, portanto, não está sendo decorado, presumo, pois ele não corresponde ao padrão em decorators.xml
.
Eu não posso fazer um <pattern>/*</pattern>
Porque existem outros JSPs que não precisam ser decorados por layout-main.jsp
. Eu não posso fazer um <pattern>/servlet/MyServlet*</pattern>
Porque MyServlet
pode encaminhar para main.jsp
Às vezes e talvez error.jsp
em outros momentos.
Existe uma maneira de contornar isso sem mudanças expansivas na maneira como os servlets funcionam? Como é um aplicativo herdado, não tenho tanta liberdade para mudar as coisas, então espero por algo em termos de configuração que conserte isso.
A documentação de Sitemesh realmente não é tão boa. Eu tenho trabalhado principalmente fora do aplicativo de exemplo que vem com a distribuição. Eu realmente gosto de Sitemesh e espero poder fazer funcionar neste caso.
Solução
Meu entendimento é que o SiteMesh é integrado ao aplicativo como um filtro de servlet. Por padrão, os filtros do servlet são chamados apenas contra a solicitação de entrada original (no seu caso, a solicitação ao servlet). Avançar ou incluir solicitações subsequentes não são passadas através do filtro e, portanto, não serão passadas através do SiteMesh.
Você pode, no entanto, instruir o filtro a ser invocado em atacantes, usando algo assim:
<filter-mapping>
<filter-name>sitemesh</filter-name>
<servlet-name>MyServlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Que instrui o contêiner a operar apenas em solicitações avançadas. As outras opções são incluem e solicitam, você pode ter vários elementos.
Portanto, suas opções são alterar sua configuração de filtro para especificar para a frente ou alterar seu mapeamento de filtro para corresponder ao caminho do servlet, em vez do caminho JSP. Qualquer um deve funcionar.