【问题标题】:Sharing static content and mvc controllers on same path在同一路径上共享静态内容和 mvc 控制器
【发布时间】:2014-08-16 03:13:24
【问题描述】:

抱歉,如果这感觉重复,我收集了很多人问这个问题,但我一直无法找到有效的答案。

我有一个使用 maven 构建的网络应用程序。我使用 Spring 4 MVC 来提供 RESTful Json API。我也有很多静态内容(html、css、js),如果我使用 Angular.js 在数据 API 上添加一个漂亮的面孔。

在我的一生中,我无法弄清楚如何在不弄乱它们的路径的情况下同时获得这两种服务。

  • 我真的很想在我的浏览器中访问{APP_ROOT}/people/{id},直接与我的 REST api 进行交互,而无需任何关于 /api//rest/ 的废话

  • 我真的很想在我的浏览器中转到{APP_ROOT}/css/style.css,并获得来自src/main/webapp/css/style.css 的内容,而不是关于resourcesstatic 的废话

  • 另外,我真的很想用带注释的 Java 类来配置所有这些,并且没有任何 web.xmlapplication-context.xml 等。

    李>

因此,Spring 调度程序 servlet 应该处理所有 REST 资源路径,然后回退到静态内容的默认 Tomcat/Jetty 处理程序。我认为这正是 default-servlet-handler 的用途?我似乎无法让它工作。

这些是我的相关配置类:

WebAppInitializer.java

public class WebAppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {


    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[0] ;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/*" };
    }

    @Override
    protected Filter[] getServletFilters() {

        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[] { characterEncodingFilter};
    }

}

WebConfig.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"my.example.package"})
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

通过此配置,我可以与 REST api 交互,但不能与静态内容交互。默认的 servlet 处理程序似乎没有效果。

【问题讨论】:

    标签: java maven spring-mvc static-content


    【解决方案1】:

    要访问像 css js 或 html 这样的静态资源,请将所有这些文件保存在模块的 webapp 文件夹中。假设您所有的静态资源都在 src/main/webapp/static 路径中,您可以在上下文 xml 中进行如下 mvc 资源映射

    <mvc:resources mapping="/index-dev.html" location="/static/index-dev.html"/>
    <mvc:resources mapping="/index.html" location="/static/index.html"/>
    <mvc:resources mapping="/app.js" location="/static/app.js"/>
    <mvc:resources mapping="/appinit.js" location="/static/appinit.js"/>
    <mvc:resources mapping="/extjs/**" location="/static/extjs/"/>
    <mvc:resources mapping="/app/**" location="/static/app/"/>
    <mvc:resources mapping="/static/**" location="/static/static/"/>
    <mvc:resources mapping="/static/**" location="/static/"/>
    

    现在,由于您想在没有 xml 的情况下执行此操作,您可以在 WebConfig 类中执行此操作,如下例所示

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/index.html").addResourceLocations("/static/index.html");
    

    }

    【讨论】:

    • 这似乎仍然不理想,因为我必须手动列出每个文件。或者我需要把事情放在一些“静态”分支中,这是我试图避免的主要事情之一。当没有有效的弹簧控制器时,肯定有一些方法可以优雅地回退到 tomcat/jetty 服务静态内容?这不就是 default-sevlet-handler 应该做的吗?
    • 另外,通过这种方法,我如何让index.html 可以直接从浏览器中的{APP_ROOT} 访问?
    • 因为在您的 servlet 中您使用的是“/*”映射,这意味着每个请求甚至是静态内容请求都必须通过 spring servlet。这就是您需要 mvc:resources 映射的原因。如果您不希望您的静态内容请求通过 spring servlet 删除“/*”,而是提供一些特定的映射,例如从 api 关键字开始的 rest api,您可以提供映射“api/*”
    猜你喜欢
    • 1970-01-01
    • 2019-12-30
    • 2017-11-21
    • 1970-01-01
    • 2012-08-08
    • 2013-07-27
    • 2011-12-19
    • 2013-06-24
    • 1970-01-01
    相关资源
    最近更新 更多