Tomcat中的URL映射到FrontController servlet

时间:2012-01-17 23:10:21

标签: tomcat servlets

我正试图遵循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一起使用?

4 个答案:

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