Spring 4 - addResourceHandlers无法解析静态资源

时间:2014-07-31 14:16:43

标签: java spring spring-mvc spring-annotations spring-4

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

Spring 4 loading static resources

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

5 个答案:

答案 0 :(得分:17)

这很有用,

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

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

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

答案 1 :(得分:13)

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

如果您给上面的配置类的调度程序servlet不是映射到根(“/”)而是映射到顶部字(例如“/ data /”),那么您可能会面临同样的问题。 / p>

假设我的调度程序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。

无论如何,我所达到的当前解决方案对我来说足够令人满意,所以我会保持原样。

答案 2 :(得分:6)

这对我有用。 /resources/js/select.js处提供的文件。注意你没有遗漏@EnableWebMvc注释....

@EnableWebMvc
@EnableTransactionManagement
public class ApplicationContextConfig extends WebMvcConfigurerAdapter {

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
        .addResourceLocations("/resources/");
    }
}

答案 3 :(得分:1)

我正在使用Spring Boot 2.2.1以及“ spring-boot-starter-web”和“ spring-boot-starter-tomcat”。就我而言,当我使用空的“ classpath:/

时,Spring Boot仅能找到“ / resources / ”文件夹。

我的文件夹结构:

enter image description here

我的代码:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
        .addResourceHandler("/resources/**")
        .addResourceLocations("classpath:/");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

使用浏览器,我可以找到任何文件,例如:

http://localhost:8080/resources/test.txt

http://localhost:8080/resources/images/background-1.png

答案 4 :(得分:0)

可以简化网页的URI只是为了包含资源的文件名:
    @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("*.css").addResourceLocations("/resources/css/"); }
适当的配置可能如下所示:

{{1}}

Spring将'/ resources / css /'字符串与从URI中提取的任何文件名连接起来,以识别资源的实际位置。