Tomcat 中的 URL 映射到 FrontController servlet

发布于 2024-12-27 13:32:56 字数 862 浏览 0 评论 0原文

我正在尝试遵循设计模式基于网络的应用程序中的模式。从映射“根”URL 开始,一切都工作得很好。

我想通过“前端控制器”发送所有请求,因此我已将其放入

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

也被控制器捕获,它再次转到操作,并且全部失败。

我可以通过不从 URL 根开始来使其工作,例如

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

但这不是我想要的。有什么方法可以让它与“根”URL 一起工作吗?

I'm trying to follow the pattern at Design Patterns web based applications. It all works fine part from when it comes to maping "root" URLs.

I'd like to put all requests through the "Front Controller" so I've put

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

in the web.xml. Stepping through with Netbeans shows the request coming in, and the Action working OK, but then the line

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

ALSO gets caught by the controller, it goes to the Action again and it all fails.

I can make it work by not going from the URL root e.g.

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

But that isn't what I want. Is there any way to make it work with "root" URLs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

傾旎 2025-01-03 13:32:56

/* URL 模式涵盖了一切,还包括转发的 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

The /* URL pattern covers everything, also the forwarded JSP files and static resources like CSS/JS/images. You don't want to have that on a front controller servlet.

Keep your controller servlet on a more specific URL pattern like /pages/*. You can achieve the functional requirement of getting rid of "/pages" in the URL by grouping the static resources in a common folder like /resources and creating a Filter which is mapped on /* and does the following job in the doFilter() method:

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

A forwarded JSP resource will by default not match this filter, so it will properly be picked up by the container's own JspServlet.

深白境迁sunset 2025-01-03 13:32:56

为什么我们需要映射每个 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;
}

否则您可以在 web.xml 中映射特定的 URL,例如

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

Why do we need to map each and every URL. In case you need to map all the URL, you might need skip URL in the filter.

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

In Your Filter,

        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           
        }

Utility Class to filter your 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 you can map specific URL in your web.xml like

<filter-mapping>
    <filter-name>sessionFilter</filter-name>
    <url-pattern>*.action</url-pattern>
  </filter-mapping>
倾其所爱 2025-01-03 13:32:56

/* url 模式匹配应用程序中的所有 servlet、jsp 和静态内容。

您需要定义一个 *.jsp 模式以允许 Tomcat 使用默认的 jsp servlet:

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

the /* url pattern matches all servlets, jsp and static content in your application.

Whay you would need is to define a *.jsp pattern to allow Tomcat use the default jsp servlet:

<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>
属性 2025-01-03 13:32:56

您可以扩展 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>

You can extend the DefaultServlet of your web server.The extended servlet will be your front controller. In the doGET or doPOST method forward your static pages to the super class. DefaultServlet is the servlet that is mapped to url "/" by default. I have used it with jetty server but it can be implemented in tomcat as well.

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

}

In the above code samples I have forwarded all the requests starting with /static/ to the default servlet to process. In this way you can map the FrontController to "/" level .

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文