1

当我将应用程序文件夹放在 {JETTY_HOME}/webapps 目录中时,我有一个运行正常的 Web 应用程序(称为 servlet)。

如果我将 Web 应用程序的副本放在 webapps 的子文件夹中,那么当我浏览到该站点时会调用所有静态文件,但我通过 ajax 调用的 servlet 返回 404。

http://localhost/shlaa
  • 正确调用 /shlaa/CommentController.do 没有错误。
http://localhost/mapapp/shlaa
  • 为 ajax 调用 /mapapp/shlaa/CommentController.do 返回 404

    两个路径 /WEB_INF 文件夹中的 web.xml 包含以下内容

    <servlet>
        <servlet-name>CommentController</servlet-name>
        <servlet-class>web.CommentController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CommentController</servlet-name>
        <url-pattern>/CommentController.do</url-pattern>
    </servlet-mapping>
    

    {JETTY_HOME}/etc 中的 jetty.xml 文件夹包含以下内容:

     <Call class="org.mortbay.jetty.webapp.WebAppContext" name="addWebApplications">
          <Arg><Ref id="contexts"/></Arg>
            <Arg><SystemProperty name="jetty.home" default="."/>/webapps</Arg>
          <Arg><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Arg>
          <Arg type="boolean">True</Arg>  <!-- extract -->
          <Arg type="boolean">True</Arg> <!-- parent priority class loading -->
      </Call> 
    
4

2 回答 2

10

为了正确地将 Java Web 应用程序部署到某个应用程序服务器或只是简单的 Web 容器(如您的情况),Web 应用程序(也称为web 模块必须具有特定的结构。Web 模块的顶级目录是应用程序的文档根目录

这是一个Web模块结构:

在此处输入图像描述

现在,您<url-pattern>web.xml文件中定义的只是某些 servlet 的逻辑/虚拟路径。同样,它不是servlet 类的物理位置的真实路径,而是逻辑路径 - 您可以根据需要进行构建。

好的,现在您必须将具有正确结构的 webapp 放在webapps目录中。例如,在上图中,Assembly Root象征着您的 webapp 文件夹。因此,您可以直接使用该文件夹,也可以制作一个 WAR(Web 应用程序存档)并将其放在webapps目录下。并不是说在webapps中有一些目录,而在那个目录中有几个 webapps。所有 Web 应用程序都必须位于 webapps 目录下。

因此,在您的情况下,如果您的 webapp 文件夹的名称为shlaa,则必须将该文件夹放在webapp. 时期。

现在引用官方 Java EE 文档:

将 URL 映射到 Web 组件

当它接收到一个请求时,Web 容器必须确定哪个 Web 组件应该处理该请求。Web 容器通过将请求中包含的 URL 路径映射到 Web 应用程序和 Web 组件来实现这一点。URL 路径包含上下文根和可选的别名:

http://host:port/context-root/alias

设置组件别名

别名标识应处理请求的 Web 组件。别名路径必须以正斜杠 (/) 开头,并以字符串或带有扩展名的通配符表达式结尾(例如,*.jsp)。由于 Web 容器会自动映射以 *.jsp 结尾的别名,因此您不必为 JSP 页面指定别名,除非您希望通过文件名以外的名称来引用该页面。

在您的情况下,您的 webapp 的 URL 将是 http://localhost:8080/shlaa

现在引用 Jetty wiki 文档(Jetty/Howto/SetContextPathto):

使用 WebAppProvider

WebAppProvider 的作用是在 ${jetty.home}/webapps/ 目录中查找任何可部署的应用程序(例如 *.war),并将它们部署到与 filename 同名的上下文中。例如,WebAppProvider 将 ${jetty.home}/webapps/MyApp-2.4.war 部署到上下文 /MyApp-2.4 中。还有一个特殊的 root.war 保留字部署到上下文 / 中。虽然这是最简单的部署机制,但它牺牲了对部署细节的控制。

长话短说,只需将您的网络应用程序放在webapps目录下即可使一切正常。至于<url-pattern>- 随意定义你喜欢的任何模式。

注意:实际上配置 Jetty 有几种方法,即 XML 配置不是唯一的一种。有关详细信息,请参阅配置 Jetty

引自The Java™ Servlet SpecificationVersion 3.0

第十二章

将请求映射到 Servlet

12.1 URL 路径的使用

收到客户端请求后,Web 容器确定将其转发到的 Web 应用程序。所选的 Web 应用程序必须具有与请求 URL 的开头匹配的最长上下文路径。URL 的匹配部分是映射到 servlet 时的上下文路径。Web 容器接下来必须找到 servlet 以使用下面描述的路径映射过程来处理请求。用于映射到 servlet 的路径是来自请求对象的请求 URL 减去上下文路径和路径参数。下面的 URL 路径映射规则按顺序使用。使用第一个成功的匹配,不再尝试匹配:

  1. 容器将尝试找到请求路径与 servlet 路径的完全匹配。成功的匹配选择 servlet。

  2. 容器将递归地尝试匹配最长的路径前缀。这是通过使用“/”字符作为路径分隔符一次将路径树下移一个目录来完成的。最长的匹配决定了选择的 servlet。

  3. 如果 URL 路径中的最后一段包含扩展名(例如 .jsp),则 servlet 容器将尝试匹配处理扩展名请求的 servlet。扩展名被定义为最后一个'.'之后的最后一段的一部分。特点。

  4. 如果前三个规则都没有导致 servlet 匹配,则容器将尝试提供适合所请求资源的内容。如果为应用程序定义了一个“默认”servlet,它将被使用。许多容器为服务内容提供了一个隐式的默认 servlet。容器必须使用区分大小写的字符串比较进行匹配。

12.2 映射规范

在 Web 应用程序部署描述符中,使用以下语法来定义映射:

  • 以“/”字符开头并以“/*”后缀结尾的字符串用于路径映射。

  • 以“*”开头的字符串。前缀用作扩展映射。

  • 空字符串 ("") 是一种特殊的 URL 模式,它精确地映射到应用程序的上下文根,即表单的请求http://host:port/<contextroot>/。在这种情况下,路径信息是“/”,servlet 路径和上下文路径是空字符串(“”)。

  • 仅包含“/”字符的字符串表示应用程序的“默认”servlet。在这种情况下,servlet 路径是请求 URI 减去上下文路径,并且路径信息为空。

  • 所有其他字符串仅用于完全匹配。

用你的名字举例。

您的 webapp 名称是mapapp(它是应用程序的根目录)。您希望您的CommentController.do可以通过

http://localhost:8080/mapapp/shlaa/CommentController.do

然后(如果满足所有其他要求,如目录结构等)在您的web.xml中放置以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <servlet>
        <servlet-name>Comment Controller</servlet-name>
        <servlet-class>com.example.CommentController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Comment Controller</servlet-name>
        <url-pattern>/shlaa/CommentController.do</url-pattern>
    </servlet-mapping>

</web-app>

/上述url 模式中的第一个正斜杠 ( )表示上下文根/上下文路径(在本例中为mapapp)。
这样它就会起作用。


这里有一些有用的链接。

Java EE 5 教程

Java EE 6 教程

码头

希望这会帮助你。


更新

对于 Jetty 特定配置,请参阅此链接:
如何让 Web 应用程序仅在特定端口上响应

于 2013-01-26T00:29:04.813 回答
1

这就是我认为正在发生的事情。

仅在 webapps 根目录和 webapps/mapapp 中克隆您的应用程序shlaa不会将您的 servlet 克隆到新位置。

静态内容有效,因为这些文件实际上存在于该位置,Jetty 将在正确的位置为它们提供服务

对于 servlet,服务器将只识别一个位置,即 shlaa/web/WEB-INF/classes 中的位置(因为您克隆了您的应用程序,我假设您的克隆将类似于 shla/mapapp/web/WEB-INF/classes)

你所要做的就是修改你的 web.xml 以便 shlaa/mapapp被识别

例如:(尝试以下组合)

<servlet-mapping>
    <servlet-name>CommentController</servlet-name>
    <url-pattern>/mapapp/CommentController.do</url-pattern>
</servlet-mapping>
于 2013-01-25T12:07:23.863 回答