2012-01-17 10 views
10

Próbuję postępować zgodnie ze wzorcem pod numerem Design Patterns web based applications. To wszystko działa świetnie, jeśli chodzi o mapowanie "root" adresów URL.Mapowanie adresów URL w Tomcat na serwlet FrontController

chciałbym umieścić wszystkie żądania przez „Front Controller”, więc umieściliśmy

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

w web.xml. Przechodzeniu z Netbeans przedstawia wniosek w najbliższych, a Akcja działa OK, ale potem linia

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

także dostaje złapany przez kontrolera, to idzie do działania i jeszcze raz to wszystko zawiedzie.

Mogę sprawić, by działał, nie wychodząc z katalogu głównego adresu URL, np.

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

Ale tego nie chcę. Czy jest jakiś sposób, aby działał z "root" adresami URL?

Odpowiedz

8

Wzór /* URL obejmuje wszystko, również przekazane pliki JSP i zasobów statycznych jak CSS/JS/images. Nie chcesz tego mieć na serwletie kontrolera frontowego.

Zachowaj serwlet kontrolera na bardziej szczegółowym wzorcu adresu URL, np. /pages/*. Można osiągnąć funkcjonalny wymóg pozbycie się „/ stron” w adresie URL poprzez grupowanie zasobów statycznych we wspólnym folderze jak /resources i tworzenie Filter który jest odwzorowany na /* i wykonuje następujące zadania w metodzie doFilter():

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); 
} 

Przesłany zasób JSP domyślnie nie będzie zgodny z tym filtrem, więc zostanie poprawnie pobrany przez własny kontener JspServlet.

+0

Dzięki za odpowiedzi, wygląda kompleks więc zajmie mi trochę czasu, aby dostać się do filtrów teraz będę po prostu zostawić wszystko w/stron/ – Mark

+0

Możesz dopasować zapytania bez rozszerzenia za pomocą path.match ("^. * \\/[^ \\.] * $") I przesłać je do kontrolera frontowego. – Ring

+0

@BalusC jaki jest sens "podciągania"? – user2418306

0

Wzór adresu/* dopasowuje wszystkie serwlety, jsp i zawartość statyczną w aplikacji.

Whay musisz jest zdefiniowanie * .jsp wzór w celu umożliwienia korzystania z serwletu Tomcat domyślny jsp:

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

Dlaczego musimy mapować każdy adres URL. Jeśli chcesz zmapować cały adres URL, możesz potrzebować pominąć URL w filtrze.

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

w filtrze, klasa

 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   
     } 

narzędzie do filtrowania 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; 
} 

Else można mapować konkretnego adresu URL w web.xml jak

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

Dziękuję za odpowiedzi, wygląda to na skomplikowane, więc zajmie mi trochę czasu, aby przejść do filtrów, na razie zostawię wszystko na/pages/ – Mark

0

Możesz rozszerzyć DefaultServlet twojego serwera sieciowego. Rozszerzony serwlet będzie twoim frontowym kontrolerem. W metodzie doGET lub doPOST przesyłaj swoje statyczne strony do super klasy. DefaultServlet jest serwletem mapowanym domyślnie na adres url "/". Użyłem go z serwerem pomostu, ale można go również zaimplementować w 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 
    } 
} 

}

W powyższych przykładach kodu I przekazywane wszystkie żądania zaczynające/statyczne/do standardowego serwlet proces. W ten sposób możesz odwzorować FrontController na poziom "/".

<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

Czy to wiąże twoje rozwiązanie z konkretnym kontenerem? Innymi słowy, kiedy piszę ten kod do mojej aplikacji, czy utknąłem z Tomcatiem lub Jetty, czy cokolwiek od tego czasu, aż będę musiał później wrócić i zmienić ten kod? – Ring

Powiązane problemy