Spring 4 - addResourceHandlers 未解析静态资源

我的maven spring项目目录结构如下所示。我正在使用基于Spring-4注释的配置。我配置了如下资源。我尝试了许多Stackoverflow问题和其他网站中建议的方法

弹簧4加载静态资源

http://imwill.com/spring-mvc-4-add-static-resources-by-annotation/#.U5GZlXKs9i4

但是 jsp 文件无法加载资源,所有静态内容请求都返回 404 错误。我在jsp中尝试了这些东西,

 <link href="resources/css/bootstrap.css" rel="stylesheet" media="screen">
 <link href="/resources/css/bootstrap.css" rel="stylesheet" media="screen">
 <link href="css/bootstrap.css" rel="stylesheet" media="screen">

编辑:我正在使用servlet 2.5,因为到目前为止,我无法将我的项目从JBoss 5升级到更高版本。JBoss5 不支持 servlet 3,这重要吗?

@Configuration
@ComponentScan("com.mgage.mvoice")
public class MyAppWebConfig extends WebMvcConfigurerAdapter {
     public void addResourceHandlers(ResourceHandlerRegistry registry) {  
        // I tried these many combinations separately.

        ResourceHandlerRegistration resourceRegistration = registry
            .addResourceHandler("resources/**");
        resourceRegistration.addResourceLocations("/resources/**");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/**");
        registry.addResourceHandler("/img/**").addResourceLocations("/img/**");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/**");
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("classpath:/resources/"); 
              // do the classpath works with the directory under webapp?
     }

}

Project structure


答案 1

这奏效了,

   registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");

在jsp文件中,我引用了静态资源,例如

<link href="resources/css/bootstrap.css" rel="stylesheet" media="screen">

答案 2

我想这有点晚了,但是我最近遇到了类似的问题。经过几天的苦苦挣扎,终于发现我的DispatcherServlet没有配置为处理请求,因此资源从未被查找过。所以我希望其他人会发现这个答案很有用。

如果您在上面给出的配置类的调度程序 servlet 不是映射到根 (“/”) 而是映射到一个顶级单词(例如 “/data/”),那么您可能会遇到同样的问题。

假设我的调度程序 servlet 有一个映射为 “/data/*”。所以我的电话看起来像

http://localhost:8080/myWebAppContext/data/command

我认为如果我有一个资源映射,例如“/content/**/*”,那么我就可以访问它

http://localhost:8080/myWebAppContent/content/resourcePath

但这不是真的,我应该使用

http://localhost:8080/myWebAppContent/data/content/resourcePath

相反。这对我来说并不清楚,并且由于大多数示例使用根“/”作为调度程序servlet的映射,因此这不是问题。在以后考虑之后,我应该更早地知道它 - /data/告诉DispatcherServlet应该评估调用,而content/告诉servlet资源处理程序是“控制器”。

但是我想在我的前端(angularJs)中非常清楚地说明我是寻找数据(通过REST服务)还是内容(返回纯文本)。数据来自数据库,但内容来自文件(例如.pdf文档)。因此,我决定向调度程序 servlet 添加两个映射:

public class MidtierWebConfig implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(MidtierAppConfig.class);

    servletContext.addListener(new ContextLoaderListener(rootContext));

    AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(MidtierDispatcherConfig.class);

    Dynamic netskolaDispatcher = servletContext.addServlet(
        "dispatcher",
        new DispatcherServlet(dispatcherContext)
    );
    netskolaDispatcher.setLoadOnStartup(1);
    netskolaDispatcher.addMapping("/data/*");
    netskolaDispatcher.addMapping("/content/*");
}

}

MidtierAppConfig 类为空,但 MidtierDispatcherConfig 定义了静态资源:

@Configuration
@ComponentScan("my.root.package")
@EnableWebMvc
public class MidtierDispatcherConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            .addResourceHandler("/courses/**/*")
            .addResourceLocations("/WEB-INF/classes/content/")
        ;
    }
}

现在,当我想访问我的@Controller时,我使用/data/前缀,当我想访问我的资源时,我使用/content/前缀。需要注意的是,如果我有一个@RequestMapping(“/app”)类,它有一个@RequestMapping(“/about”)方法,那么data/app/about和content/app/about都会只调用该方法(如果没有实际尝试,我想我可能会以/app/courses/whatEverPath的形式访问资源),因为调度程序同时监听“data/”和“content/”, 并仅分析URL的其余部分(在这两种情况下都是“app/about”),以找到正确的@Controller。

无论如何,我目前达成的解决方案对我来说已经足够令人满意了,所以我将保持原样。


推荐