Отображение URL-адреса в Tomcat для сервлета FrontController

Я пытаюсь следовать шаблону в веб-приложениях Design Patterns. Все это отлично работает, когда речь идет о создании "корневых" URL-адресов.

Я хотел бы передать все запросы через "Front Controller", поэтому я поставил

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

в web.xml. Прохождение через Netbeans показывает запрос, входящий, и действие работает нормально, но затем строка

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

ТАКЖЕ попадает на контроллер, он снова возвращается к Action, и все это терпит неудачу.

Я могу заставить его работать, не перейдя из корня URL, например.

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

Но это не то, что я хочу. Есть ли способ заставить его работать с "корневыми" URL-адресами?

Ответ 1

Шаблон URL /* охватывает все, а также пересылаемые JSP файлы и статические ресурсы, такие как CSS/JS/images. Вы не хотите иметь это на сервлете переднего контроллера.

Держите сервлет вашего контроллера более определенным шаблоном URL, например /pages/*. Вы можете достичь функционального требования избавиться от "/страниц" в URL-адресе, группируя статические ресурсы в общей папке типа /resources и создавая Filter, который отображается на /*, и выполняет следующее задание в doFilter() метод:

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

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

Переадресованный ресурс JSP по умолчанию не будет соответствовать этому фильтру, поэтому он будет правильно выбран контейнером JspServlet.

Ответ 2

Зачем нам нужно сопоставлять каждый URL. Если вам нужно отобразить все URL-адреса, вам может понадобиться пропустить URL-адрес в фильтре.

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

В своем фильтре

        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           
        }

Класс полезности для фильтрации вашего 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;
}

Иначе вы можете сопоставить определенный URL-адрес в своем web.xml, например

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

Ответ 3

шаблон/* url соответствует всем сервлетам, jsp и статическому содержимому в вашем приложении.

Вам понадобится определить шаблон *.jsp, чтобы Tomcat использовал сервлет по умолчанию jsp:

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

Ответ 4

Вы можете расширить DefaultServlet вашего веб-сервера. Расширенный сервлет будет вашим передним контроллером. В методе doGET или doPOST пересылайте свои статические страницы в суперкласс. DefaultServlet - это сервлет, который по умолчанию отображается на url "/". Я использовал его с сервером причала, но его можно реализовать и в 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
    }
}

}

В приведенных выше примерах кода я отправил все запросы, начинающиеся с /static/, на сервлет по умолчанию для обработки. Таким образом вы можете сопоставить FrontController с уровнем "/".

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