【问题标题】:Spring 4 - addResourceHandlers not resolving the static resourcesSpring 4 - addResourceHandlers 不解析静态资源
【发布时间】:2014-07-31 14:16:42
【问题描述】:

我的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?
     }

}

【问题讨论】:

  • 您需要预先添加您的 Web 应用程序的上下文路径。
  • 但是,这不会对上下文进行硬编码吗?我想知道它如何使用相同的配置,但在 xml 配置中,spring-3.2.6!
  • 你不会硬编码任何东西:stackoverflow.com/questions/12705193/…

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


【解决方案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 类为空,但 M​​idtierDispatcherConfig 定义了静态资源:

@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("/about") 方法的 @RequestMapping("/app") 类,那么 data/app/about 和 content/app/about 都将调用该方法(并且没有实际尝试,我想我也可能以 /app/courses/whatEverPath 的形式访问资源),因为调度程序同时监听“data/”和“content/”,并且只分析 url 的其余部分(“app/about " 在这两种情况下) 来找到正确的@Controller。

不管怎样,目前我已经达到的解决方案对我来说已经足够满意了,所以我会保持原样。

【讨论】:

  • 谢谢!我试图在同一上下文中配置两个 servlet:一个用于 REST api,另一个用于 Swagger 文档。你的帖子很有帮助;)
【解决方案3】:

这对我有用。 /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/");
    }
}

【讨论】:

    【解决方案4】:

    我正在使用 Spring Boot 2.2.1 和“spring-boot-starter-web”和“spring-boot-starter-tomcat”。在我的情况下,当我使用空的“classpath:/

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

    我的文件夹结构:

    我的代码:

    @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

    【讨论】:

      【解决方案5】:

      可以将网页的 URI 简化为仅包含资源的文件名:
      &lt;link href="bootstrap.css" rel="stylesheet" media="screen"&gt;
      适当的配置可能如下:

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

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

      【讨论】:

      • 这很有用,直到您想要分离 css 文件(比如主题)。此方法假定 css 文件将始终位于一个目录结构中。您将无法区分 resources/theme1/cssresources/theme2/css
      • @coderatchet 这应该不是问题,与 Spring 无关。首先,您需要将主题的 css 放在像 resources/css/theme1resources/css/theme2 这样的结构中。然后你会使用你的css作为href="theme1/styles.css"。使用您描述的结构,无论框架如何,您都会遇到问题,因为在逻辑上不可能区分类似的东西。
      • registry.addResourceHandler("**/*.css).addResourceLocations("/")
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-05
      • 2017-04-07
      • 1970-01-01
      • 2016-10-01
      • 2011-12-30
      相关资源
      最近更新 更多