我正试图遵循Design Patterns web based applications的模式。从maping“root”URL开始,这一切都很好。
我想通过“Front Controller”发出所有请求,所以我已经把
<servlet-mapping>
<servlet-name>ControllerServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
web.xml
中的。通过Netbeans逐步显示请求进入,并且Action工作正常,但接着是行
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一起使用?
答案 0 :(得分:8)
/*
网址格式涵盖所有内容,还包括转发的JSP文件和CSS / JS /图像等静态资源。您不希望在前端控制器servlet上拥有它。
将控制器servlet保持在更具体的URL模式,如/pages/*
。您可以通过将静态资源分组到/resources
等公共文件夹中并创建映射到Filter
上的/*
来实现删除URL中“/ pages”的功能要求。在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);
}
默认情况下,转发的JSP资源与此过滤器不匹配,因此容器自己JspServlet
将正确选择它。
答案 1 :(得分:3)
为什么我们需要映射每个网址。如果您需要映射所有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
}
过滤网址的实用工具类:
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;
}
否则,您可以在web.xml中映射特定的URL,如
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
答案 2 :(得分:0)
/ * url模式匹配应用程序中的所有servlet,jsp和静态内容。
你需要的是定义一个* .jsp模式以允许Tomcat使用默认的jsp servlet:
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
答案 3 :(得分:0)
您可以扩展Web服务器的DefaultServlet。扩展的servlet将是您的前端控制器。在doGET或doPOST方法中,将静态页面转发到超类。 DefaultServlet是默认情况下映射到url“/”的servlet。我已经将它用于jetty服务器,但它也可以在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 /开头的请求转发到要处理的默认servlet。通过这种方式,您可以将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>