关于 Servlet 绑定模式和默认 servlet

About Servlet binding patterns and default servlet

我有一个要绑定到 "/" 模式的 Servlet。之后,所有 URL 都可以正常工作,包括应用程序根目录,但我还需要 default servlet 来支持静态文件。

在我以这种方式将其添加到 web.xml 之后,我在应用程序根目录 URL 处遇到了 404 错误,但所有其他 URL 仍由分配给 "/".

的 Servlet
<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*.html</url-pattern>
  <url-pattern>*.css</url-pattern>
  <url-pattern>*.js</url-pattern>
<servlet-mapping>

在我将 Servlet 也绑定到 "" 模式后,它工作正常。我对这种模式的理解与应用程序的根 URL 有关。

你能帮我找出这种行为的原因吗?

P.S。我用 TomCat 和 Undertow 检查行为。

我使用 Apache Tomcat 9.0.21 和以下 servlet 重现了您的问题:

package my.sample;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("servlet1: " + req.getServletPath());
    }
}

和web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    id="myApp" version="4.0">
    <display-name>myWebApp</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>servlet1</servlet-name>
        <servlet-class>my.sample.Servlet1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.css</url-pattern>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
</web-app>

如您所述,打开 URL http://localhost:8080/myWebApp/ 会导致错误 404。其他 URL 不匹配任何 default servlet url-pattern 由我的 servlet1 处理并产生类似 servlet1: /hello 的输出,例如打开 http://localhost:8080/myWebApp/hello

default servlet 映射中删除 <url-pattern>*.html</url-pattern> 时,您的问题消失了,我在打开 http://localhost:8080/myWebApp/.

时收到 servlet1: / 作为响应

<url-pattern>*.html</url-pattern> 添加到 servlet1 servlet 映射时,我在打开 http://localhost:8080/myWebApp/.

时得到 servlet1: /index.html 作为响应

这表明您的问题的原因是路径 / 在内部转发到欢迎文件 index.html,它与 *.html url- 完全匹配在您的案例中为 default servlet 配置的模式 - 因此选择 default servlet 来处理 / 请求路径。如果 index.html 不存在,default servlet 将发送您观察到的 404 错误。