Отображение 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>