【问题标题】:How to use default-servlet-handler如何使用 default-servlet-handler
【发布时间】:2011-11-05 20:54:07
【问题描述】:

我想配置 Spring MVC 以提供与静态文件混合的动态文件,如下所示(URL => 文件):

/iAmDynamic.html   => /WEB-INF/views/iAmDynamic.html.ftl
/iAmAlsoDynamic.js => /WEB-INF/views/iAmAlsoDynamic.js.ftl
/iAmStatiHtml      => /iAmStatic.html

DispatchServlet 映射到 /,启用了基于注释的 MVC 配置,并且我有一个这样的视图控制器(简化):

@Controller
public class ViewController
{
    @RequestMapping("*.html")
    public String handleHtml(final HttpServletRequest request)
    {
         return request.getServletPath();
    }

    @RequestMapping("*.js")
    public String handleJavaScript(final HttpServletRequest request)
    {
        return request.getServletPath();
    }
}

spring 配置如下所示:

<context:component-scan base-package="myPackage" />

<mvc:default-servlet-handler />

<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  <property name="templateLoaderPath" value="/WEB-INF/views/" />
</bean>

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
  <property name="cache" value="true" />
  <property name="prefix" value="" />
  <property name="suffix" value=".ftl" />
</bean>

不幸的是,它不起作用。当这个&lt;mvc:default-servlet-handler /&gt; 处于活动状态时,我只能访问iAmStatic.html 文件。当我禁用 default-servlet-handler 时,只有动态的东西起作用。但我同时想要这两个,这正是这个 default-servlet-handler 应该做的,或者不是?这里的错误在哪里?

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

    我遇到了类似的问题,没有一个请求被映射到 Spring 控制器: 我发现我在 spring config xml 中丢失了这个:

    <mvc:annotation-driven/>
    

    看来,这是必要的。从文档来看,这样做的目的是:

    Configures the annotation-driven Spring MVC Controller programming model
    

    我还将让 DefaultServlet 处理静态内容请求。

    所以你的 spring 配置应该是这样的:

    <context:component-scan base-package="myPackage" />
    <!-- Define location and mapping of static content -->
    <mvc:resources location="/static/" mapping="/static/**"/>
    
    <mvc:default-servlet-handler />
    <mvc:annotation-driven/>
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
      <property name="templateLoaderPath" value="/WEB-INF/views/" />
    </bean>
    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
      <property name="cache" value="true" />
      <property name="prefix" value="" />
      <property name="suffix" value=".ftl" />
    </bean>
    

    希望这会有所帮助!

    【讨论】:

    • 那为什么不使用视图控制器呢?
    【解决方案2】:

    你需要定义两个重要的配置

    <mvc:annotation-driven/>
    <mvc:default-servlet-handler />
    

    &lt;mvc:annotation-driven/&gt; 将启用您的默认基础设施 bean,而 &lt;mvc:default-servlet-handler /&gt; 将配置一个处理程序,通过转发到 Servlet 容器的默认 Servlet 来提供静态资源。

    也不要忘记 mvc 命名空间,即xmlns:mvc="http://www.springframework.org/schema/mvc"

    我的完整配置文件(使用 TilesViewResolver)如下所示

    <?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/mvc 
                            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <mvc:annotation-driven/>
    
        <!-- 
          Configures a handler for serving static resources by forwarding to the 
          Servlet container's default Servlet. 
        -->
        <mvc:default-servlet-handler />
    
        <mvc:view-controller path="/" view-name="welcome"/>
        <mvc:view-controller path="/home" view-name="welcome"/>
    
        <bean class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
            <property name="definitions">
                <list>
                    <value>/WEB-INF/tiles.xml</value>
                </list>
            </property>
        </bean> 
    
        <bean class="org.springframework.web.servlet.view.tiles3.TilesViewResolver">
            <property name="order" value="1"/>
        </bean> 
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="order" value="2"/>
            <property name="prefix" value="/WEB-INF/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    

    另外,如果您有多个 HandlerMapping 考虑订购它们。对于您没有明确提供顺序的人,Spring 以最低优先级对待它。

    【讨论】:

    • 那为什么不使用视图控制器呢?
    【解决方案3】:

    我认为您从ViewController 返回的视图名称无效。我希望 request.getServletPath() 为所有 URL 返回一个空白字符串,因为您的 servlet 的路径可能是 / 并且 Java 文档说 getServletPath() 为该路径返回一个空白字符串。因此,FreeMarker 视图解析器可能会忽略视图名称,因为它不知道要显示什么。

    然而,使用带有@RequestMapping 的控制器类可能不是完成这项任务的理想方式。 Spring 包含一个ContentNegotiatingViewResolver,它会根据内容类型自动确定正确的视图。 This overview of ContentNegotiatingViewResolver 解释了如何设置它。

    【讨论】:

      猜你喜欢
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-14
      • 2015-09-29
      相关资源
      最近更新 更多