2012-01-17 29 views
10

Estoy intentando seguir el patrón en Design Patterns web based applications. Todo funciona bien desde el punto de vista de la creación de URL "raíz".Asignación de URL en Tomcat al servlet FrontController

me gustaría poner todas las solicitudes a través del "Front Controller", por lo que he puesto

<servlet-mapping> 
    <servlet-name>ControllerServlet</servlet-name> 
    <url-pattern>/*</url-pattern> 
</servlet-mapping> 

en el web.xml. Dando un paso adelante con Netbeans muestra la petición de entrada, y la acción que trabaja bien, pero entonces la línea

request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response); 

TAMBIÉN se ve atrapado por el controlador, se va a la acción de nuevo y todo falla.

Puedo hacerlo funcionar al no ir desde la raíz de URL, p.

<servlet-mapping> 
     <servlet-name>ControllerServlet</servlet-name> 
     <url-pattern>/pages/*</url-pattern> 
    </servlet-mapping> 

Pero eso no es lo que quiero. ¿Hay alguna forma de hacerlo funcionar con URL "raíz"?

Respuesta

8

El patrón /* URL cubre todo , también los archivos JSP reenviados y recursos estáticos como CSS/JS/images. No desea tener eso en un servlet de controlador frontal.

Mantenga el servlet de su controlador en un patrón de URL más específico como /pages/*. Se puede lograr el requisito funcional de deshacerse de "/ páginas" en la URL mediante la agrupación de los recursos estáticos en una carpeta común como /resources y creando un Filter que está mapeado en /* y hace el siguiente trabajo en el doFilter() método:

HttpServletRequest req = (HttpServletRequest) request; 
String path = req.getRequestURI().substring(req.getContextPath().length()); 

if (path.startsWith("/resources/")) { 
    // Just let container's default servlet do its job. 
    chain.doFilter(request, response); 
} else { 
    // Delegate to your front controller. 
    request.getRequestDispatcher("/pages" + path).forward(request, response); 
} 

Un recurso JSP reenviado por defecto no coincidirá con este filtro, por lo que será correctamente recogido por el propio contenedor JspServlet.

+0

Gracias por las respuestas, parece compleja por lo que me va a tomar un tiempo para llegar a los filtros, por ahora sólo voy a dejar todo en/pages/ – Mark

+0

Puede hacer coincidir solicitudes sin extensión con path.match ("^. * \\/[^ \\.] * $") Y reenviarlo a su controlador frontal. – Ring

+0

@BalusC ¿cuál es el punto de 'substring'? – user2418306

0

el/* patrón url coincide con todos los servlets, jsp y contenido estático en su aplicación.

whay que se necesita es definir un patrón * .jsp para permitir Tomcat utilizar el servlet jsp defecto:

<servlet-mapping> 
    <servlet-name>jsp</servlet-name> 
    <url-pattern>*.jsp</url-pattern> 
</servlet-mapping> 
3

¿Por qué tenemos que asignar todas y cada una de las URL? En caso de que necesite mapear toda la URL, es posible que necesite omitir la URL en el filtro.

<filter> 
    <display-name>SessionFilter</display-name> 
    <filter-name>SessionFilter</filter-name> 
    <filter-class>com.colabcom.goshare.app.base.filter.SessionFilter</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>sessionFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 

en el filtro, Clase

 HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 
     String url = request.getServletPath(); 
     boolean allowedRequest = Utility.filterURL(url, avoidUrls); 
     if(allowedRequest){ 
      chain.doFilter(request, response); 
     }else{ 
      //Main Filter Code   
     } 

utilidad para filtrar la URL:

public static boolean filterURL(String str, List<String> avoidURLList) { 
    boolean exist = false; 

    if(avoidURLList == null){ 
     return exist; 
    } 
    for (int i = 0; i < avoidURLList.size(); i++) { 
     if (str.contains(avoidURLList.get(i))) { 
      exist = true; 
      break; 
     } 
    } 
    return exist; 
} 

Cosa que usted puede asignar URL específica en su web.xml como

<filter-mapping> 
    <filter-name>sessionFilter</filter-name> 
    <url-pattern>*.action</url-pattern> 
    </filter-mapping> 
+0

Gracias por las respuestas, parece complejo, así que me tomará un tiempo llegar a los filtros, por ahora lo dejaré todo en/pages/ – Mark

0

Puede extender el DefaultServlet de su servidor web. El servlet extendido será su controlador frontal. En el método doGET o doPOST reenvía tus páginas estáticas a la superclase. DefaultServlet es el servlet que está mapeado a url "/" de forma predeterminada. Lo he usado con el servidor de embarcadero, pero también se puede implementar en tomcat.

public class FrontController extends DefaultServlet { 

@Override 
public void init() throws UnavailableException { 
    super.init(); 
} 

@Override 
protected void doGet(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 

    String uri = request.getRequestURI(); 

    /* 
    * if request is trying to access inside /static then use the default 
    * servlet. YOU CAN USE YOUR OWN BUSINESS LOGIC TO FORWARD REQUESTS 
    * TO DEFAULTSERVLET 
    */ 
    if (uri.startsWith("/static/")) { 

     super.doGet(request, response); 
     return; 
    } else { 

     // else use your custom action handlers 
    } 
} 

}

En los anteriores ejemplos de código He remitido todas las peticiones que empiezan con/a la servlet estática/default para procesar. De esta forma, puede asignar el FrontController al nivel "/".

<servlet> 
<description></description> 
<display-name>FrontController</display-name> 
<servlet-name>FrontController</servlet-name> 
<servlet-class>FrontController</servlet-class> 

<servlet-mapping> 
<servlet-name>FrontController</servlet-name> 
<url-pattern>/</url-pattern> 

+0

¿Esto vincula su solución a un contenedor específico? En otras palabras, una vez que escribo este código en mi aplicación, ¿estoy atascado con Tomcat o Jetty o lo que sea a partir de ese momento, hasta que luego tenga que volver y cambiar este código? – Ring

Cuestiones relacionadas