为什么WEB-INF文件夹中的jsp文件可以工作,而放在WEB-INF下的文件夹下却不能呢?


问题内容

当我的jsp文件位于WEB-INF文件夹(如/WEB-INF/file.jsp)中时,我可以从本地主机访问它们:8080 / ProjectCtxtRoot
/,但如果将它们放在/ WEB-中,则无法访问它们。 INF / jsp / file.jsp?

我更改了web.xml中的welcome-list标记中的路径,如下所示

<welcome-file-list>
       <welcome-file>/JSP/fileName.jsp</welcome-file>
</welcome-file-list>

我还如下更改了dispatcher-servlet.xml

   <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />

仍然不起作用。以上情况使用的网址是

 localhost:8080/ContextRoot/jsp/
 localhost:8080/ContextRoot/jsp/fileName.jsp
 localhost:8080/ContextRoot/jsp/fileName

并且不适用于上述任何网址。

但它在工作时

 <welcome-file-list>
       <welcome-file>/fileName.jsp</welcome-file>
</welcome-file-list>

dispatcher-servlet.xml如下

<bean id="jspViewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver"
      p:prefix="/WEB-INF/"
      p:suffix=".jsp" />

用于上述情况的网址是localhost:8080 / ContextRoot /,并且可以正常工作。

我使用的是tomcat v 7.0服务器。我在Eclipse IDE中刷新项目,然后清理,构建,使用mvn clean
install构建war,然后从tomcat Manager主页中选择war并进行部署。我每次都这样做。

这就是diapatcher-servlet.xml在整个过程中的外观。我只是像上面所说的那样更改特定的部分

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd     
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <mvc:annotation-driven/>

    <context:component-scan base-package="com.projectName.www" />

    <!-- Factory bean that creates the Mongo instance -->
    <bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
        <property name="host" value="localhost" />
    </bean>

    <!-- MongoTemplate for connecting and quering the documents in the database -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongo" ref="mongo" />
        <constructor-arg name="databaseName" value="tableName" />
    </bean>

    <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />



    <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />

  <!--   <bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver"/>

    <bean class=
    "org.springframework.web.servlet.view.tiles2.TilesConfigurer"> -->
 <!--  <property name="definitions">
    <list>
      <value>/WEB-INF/views/views.xml</value>
    </list>
  </property> 
</bean> -->




</beans>

这就是我的web.xml的样子

<web-app>

<!--   <display-name>Archetype Created Web Application</display-name> -->

   <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/src/main/webapp/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>

   <!--  <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener> -->

    <welcome-file-list>
       <welcome-file>/fileName.jsp</welcome-file>
    </welcome-file-list>


</web-app>

好。当我将整个jsp文件夹从/webapp/WEB-
INF/jsp/fileName.jsp移到/webapp/jsp/fileName.jsp时,它可以工作。我想知道1.为什么现在可以使用?2.这是做事的正确方法吗?3.在url为localhost:8080
/ CtxtRoot / jsp /或localhost:8080 / CtxtRoot / jsp /
search.jsp时有效,但不适用于localhost:8080 / AnnaUnivResults / jsp / search。为什么会这样呢?


问题答案:

我认为这里有几个问题:

  1. 您对Spring MVC的路径感到困惑
  2. 您没有正确配置Web xml

不幸的是,我无法为您提供所有细节,很多弹簧是可配置的,因此我的解释仅涵盖最基本的情况。如果有人发现错误,请告诉我,我会解决。

对于路径,逐步思考可能会有所帮助。

  1. 您从浏览器请求URL,浏览器查看协议,主机和端口,并使用DNS查找要连接的适当IP地址。
  2. 在浏览器和主机之间建立了连接。主机查找在您指定的端口上运行的进程,如果任何安全系统允许TCP连接,则请求将流式传输到在该端口(Web服务器)上运行的进程。
  3. Web服务器根据端口后面的内容进行决策,具体地说,它通过查看给定的路径来确定Web应用程序上下文是什么。一旦确定了应用程序上下文根,便知道哪个Web应用程序应处理该请求。该决定取决于您如何配置Web服务器,可以使Web应用程序处理没有​​上下文根或特定上下文根的请求。例如,如果您请求localhost:8080/CtxtRoot/jsp/,则服务器上可以有一个Web应用程序,其上下文根为“ CtxtRoot”,它将处理该请求。或者,您可能有一个上下文带有“”的应用程序,并且可以处理该请求。这取决于您配置服务器的方式,默认情况下,Tomcat将使用war名称作为上下文根。
  4. Web应用程序收到请求。虽然知道请求的完整URL,但它仅基于上下文根之后的所有内容进行决策。因此,例如,以的请求localhost:8080/CtxtRoot/jsp/,Web应用程序将基于“ jsp”作为路径路由事物。
  5. Web应用程序具有一个筛选器链,它首先将请求提交给它。如果过滤器的模式与请求匹配,则该过滤器可以评估该请求。它可能会阻止请求,处理请求或将其传递。我不会说太多,因为您的问题不涉及过滤器。
  6. 该Web应用程序查找其模式与请求匹配的资源,首先考虑servlet,然后再考虑静态资源。上下文之后出现的url部分是它尝试匹配的内容,因此,如果请求是针对localhost:8080/CtxtRoot/jsp/,并且上下文根是“ CtxtRoot”,则Web应用程序会将“ / jsp /”与所有servlet映射进行比较。对WEB-INF中的静态资源的请求将始终被拒绝,但是Servlet和过滤器可以并且确实从WEB-INF返回数据。
  7. 我将继续假设请求已发送到spring DispatcherServlet,它接收到请求,并考虑servlet路径之后的所有内容。Spring的DispatcherServlet寻找一个控制器,该控制器的路径与Servlet路径之后的路径相匹配。servlet路径基本上就是您在Web xml中的servlet映射中放置的路径。让我举个例子,假设您有一个Web应用程序,其上下文为“ app”,并且它具有一个Spring MVC servlet,其servlet映射为“ / mvc”,以及一个处理路径“ sales”的控制器,那么您可以通过到达那个控制器http://localhost:8080/app/mvc/sales
  8. 如果DispatcherServlet找不到控制器,我认为它将传入请求视为由控制器返回,因此,如果子路径为“ sales”,则它将其作为参数传递给视图解析器。如果找不到,则服务器返回未找到的错误。
  9. 通常,Controller完成后会返回一个字符串,这是资源的路径。它可以返回“ popular”作为字符串。然后,Spring将其转发到ViewResolver,我将假设您正在使用InternalResourceViewResolver。它将查看前缀和后缀,并基本上将其包装在给出的内容周围。因此,如果前缀为“ / WEB-INF / views /”,后缀为“ .jsp”,参数为“ popular”,则它将在“ /WEB-INF/views/popular.jsp”中查找资源。 ‘。从字面上看,它只是将那些字符串连接起来以构成路径。此处的路径始终是相对于Web应用程序根目录的路径。如果生成的路径是一个jsp文件,它将在返回之前被解释。
  10. 然后最终将其返回给用户。

在您的示例中,您请求的是localhost:8080 / ContextRoot / jsp /
fileName,因此看起来’CtxRoot’是上下文根,您的servlet的路径是’/’,因此它将之后的内容传递给控制器​​。当DispatcherServlet收到请求时,它正在搜索将“
jsp”作为路径处理的控制器。由于您一无所有,因此它决定将其视为资源路径。它使用视图解析器,并形成了/WEB-
INF/jsp/jsp/fileName.jsp路径,该路径显然不存在。

假设您改为请求localhost:8080 / ContextRoot / fileName,该请求将到达DispatcherServlet,它将找不到将“
fileName”作为路径处理的Controller,因此会将其视为资源。它会形成路径/WEB-INF/jsp/fileName.jsp,并返回结果。

但是,您的Web
xml未配置为初始化spring。因此,您的Web应用程序实际上在对待您的每个请求,就好像它们是相对于Web应用程序根目录的资源一样。我相信,如果您使用Spring正确初始化了该请求,那么它可能会起作用。

这是一个很好的例子:

http://www.mkyong.com/spring3/spring-3-mvc-hello-world-
example/

请注意,他的Web
xml具有一个ContextLoaderListener,在您的注释中将其注释掉,这对于在Web应用程序中初始化spring至关重要。我还可以在调度程序中看到带有/
src / main / resources路径的注释,但是应该将Web
xml中的所有路径都相对于Web应用程序根目录。在运行时,Web服务器不了解您的项目,并且“
src”不是Web应用程序根目录中的目录。还要注意,您的MVC内容可以具有与主Spring上下文不同的应用程序上下文,这很常见。

我认为,如果您执行以下操作,它将起作用:

  1. 将您的jsp移至/WEB-INF/jsp/fileName.jsp
  2. 更新您的应用程序上下文,使“ / WEB-INF / jsp /”为前缀,而“ .jsp”为后缀。
  3. 将上下文加载器侦听器添加到您的Web xml,并设置相对于应用上下文根目录的contextConfigLocation路径。例如,它可能是/WEB-INF/appContext.xml
  4. 提出要求

本地主机:8080 / CtxtRoot / fileName

另外,您一直在谈论欢迎文件,但是您在提供资源的完整路径。仅当用户向目录的根目录发出请求时,欢迎文件才会起作用,如下所示:

localhost:8080/CtxtRoot/

该请求将被转发到欢迎文件。我认为,只有当您尝试这样做时,jsp恰好位于应用程序的根目录中,并被配置为欢迎文件,因此它可以正常工作。当它“工作”时,它实际上并没有使用spring来返回它。

祝你好运。