SpringBoot中静态资源映射处理

简介: SpringBoot中静态资源映射处理

上一篇博文说明了SpringBoot对WebJars的支持,那么项目中还有其他静态资源文件,如自定义CSS、JS、image等,SpringBoot同样提供了映射支持。


【1】静态资源文件映射规则


同样查看WebMvcAutoConfiguration源码如下:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
  if (!this.resourceProperties.isAddMappings()) {
    logger.debug("Default resource handling disabled");
    return;
  }
  //对webjars做映射处理
  Integer cachePeriod = this.resourceProperties.getCachePeriod();
  if (!registry.hasMappingForPattern("/webjars/**")) {
    customizeResourceHandlerRegistration(
        registry.addResourceHandler("/webjars/**")
            .addResourceLocations(
                "classpath:/META-INF/resources/webjars/")
        .setCachePeriod(cachePeriod));
  }
  // 对静态资源文件映射支持
  String staticPathPattern = this.mvcProperties.getStaticPathPattern();
  if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(
        registry.addResourceHandler(staticPathPattern)
            .addResourceLocations(
                this.resourceProperties.getStaticLocations())
        .setCachePeriod(cachePeriod));
  }
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/upload/**").addResourceLocations("file:"+"D://javasoftinstall/upload/");
registry.addResourceHandler("/**")
    .addResourceLocations("classpath:/resources/")
    .addResourceLocations("classpath:/static/")
super.addResourceHandlers(registry);
}


这里可以看到对静态资源处理的具体支持代码如下:

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
  if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(
        registry.addResourceHandler(staticPathPattern)
            .addResourceLocations(
                this.resourceProperties.getStaticLocations())
        .setCachePeriod(cachePeriod));
  }


第一步拿到staticPathPattern;

/**
 * Path pattern used for static resources.
 */
private String staticPathPattern = "/**";

第二步,如果资源请求没有对应映射,就添加资源处理器及资源找寻位置并设置缓存

if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(
        registry.addResourceHandler(staticPathPattern)
            .addResourceLocations(
                this.resourceProperties.getStaticLocations())
        .setCachePeriod(cachePeriod));
  }


其中 staticLocations在ResourceProperties类中,源码如下:

/**
 * Properties used to configure resource handling.
 */
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
  private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" };
//静态资源映射路径
  private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
      "classpath:/META-INF/resources/", "classpath:/resources/",
      "classpath:/static/", "classpath:/public/" };
  private static final String[] RESOURCE_LOCATIONS;
  static {
    RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
        + SERVLET_RESOURCE_LOCATIONS.length];
    System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
        SERVLET_RESOURCE_LOCATIONS.length);
    System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
        SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
  }
  /**
   * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
   * /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
   */
  private String[] staticLocations = RESOURCE_LOCATIONS;

即:"/**" 访问当前项目的任何资源,只要没有匹配的处理映射,则都去静态资源的文件夹找映射

"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径


如下图,访问static/asserts/img/bootstrap-solid.svg:


20180613142325845.jpg


URL : http://localhost:8083/asserts/img/bootstrap-solid.svg;


这里注意URL上面不要添加静态资源文件夹(路径)的名字,如static、public等等。


【2】默认欢迎页的映射

代码如下:

    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(
        ResourceProperties resourceProperties) {
      return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),
          this.mvcProperties.getStaticPathPattern());
    }

注册了WelcomePageHandlerMappingBean来处理项目的默认欢迎页面,构造器有两个参数,第一个是项目中存在的欢迎页资源,第二个是静态资源路径映射规则。


① 获取欢迎页资源

其中跟踪resourceProperties.getWelcomePage()源码:

  public Resource getWelcomePage() {
    for (String location : getStaticWelcomePageLocations()) {
      Resource resource = this.resourceLoader.getResource(location);
      try {
        if (resource.exists()) {
          resource.getURL();
          return resource;
        }
      }
      catch (Exception ex) {
        // Ignore
      }
    }
    return null;
  }



即找到存在的欢迎页的资源,继续跟getStaticWelcomePageLocations()源码:

private String[] getStaticWelcomePageLocations() {
    String[] result = new String[this.staticLocations.length];
    for (int i = 0; i < result.length; i++) {
      String location = this.staticLocations[i];
      if (!location.endsWith("/")) {
        location = location + "/";
      }
      result[i] = location + "index.html";
    }
    return result;
  }


即 欢迎页的位置为第【1】部分中静态资源文件路径下的index.html。

如下所示:

"classpath:/META‐INF/resources/index.html",
"classpath:/resources/index.html",
"classpath:/static/index.html",
"classpath:/public/index.html"
"/":/index.html


② 静态路径映射规则

  /**
   * Path pattern used for static resources.
   */
  private String staticPathPattern = "/**";

③ WelcomePageHandlerMapping类

static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
    private static final Log logger = LogFactory
        .getLog(WelcomePageHandlerMapping.class);
    private WelcomePageHandlerMapping(Resource welcomePage,
        String staticPathPattern) {
      if (welcomePage != null && "/**".equals(staticPathPattern)) {
        logger.info("Adding welcome page: " + welcomePage);
        ParameterizableViewController controller = new ParameterizableViewController();
        controller.setViewName("forward:index.html");
        setRootHandler(controller);
        setOrder(0);
      }
    }
    @Override
    public Object getHandlerInternal(HttpServletRequest request) throws Exception {
      for (MediaType mediaType : getAcceptedMediaTypes(request)) {
        if (mediaType.includes(MediaType.TEXT_HTML)) {
          return super.getHandlerInternal(request);
        }
      }
      return null;
    }
    private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) {
      String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);
      return MediaType.parseMediaTypes(
          StringUtils.hasText(acceptHeader) ? acceptHeader : "*/*");
    }
  }

总结:项目访问时,请求如http://localhost:8083/,则SpringBoot会从静态资源文件路径下找index.html,如果存在一个这样的资源,就转发请求到该页面。


【3】项目浏览器图标的映射

SpringBoot同样对项目浏览器图标请求映射做了默认配置。浏览器图片即项目访问时,浏览器页面上呈现的图标,如CSDN图标如下


代码如下:

    @Configuration
    @ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
    public static class FaviconConfiguration {
      private final ResourceProperties resourceProperties;
      public FaviconConfiguration(ResourceProperties resourceProperties) {
        this.resourceProperties = resourceProperties;
      }
      @Bean
      public SimpleUrlHandlerMapping faviconHandlerMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
            faviconRequestHandler()));
        return mapping;
      }
      @Bean
      public ResourceHttpRequestHandler faviconRequestHandler() {
        ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
        requestHandler
            .setLocations(this.resourceProperties.getFaviconLocations());
        return requestHandler;
      }
    }

跟踪源码this.resourceProperties.getFaviconLocations()如下:

List<Resource> getFaviconLocations() {
    List<Resource> locations = new ArrayList<Resource>(
        this.staticLocations.length + 1);
    if (this.resourceLoader != null) {
      for (String location : this.staticLocations) {
        locations.add(this.resourceLoader.getResource(location));
      }
    }
    locations.add(new ClassPathResource("/"));
    return Collections.unmodifiableList(locations);
  }


即在静态资源文件下找所有的favicon.ico !

目录
相关文章
|
18天前
|
JSON Java 数据格式
springboot中表字段映射中设置JSON格式字段映射
springboot中表字段映射中设置JSON格式字段映射
48 1
|
6月前
|
Java Maven Spring
SpringBoot-读取配置文件(映射法)
本文是关于Spring Boot框架下读取配置文件的指南。该指南介绍了如何通过注解和属性文件来加载和访问应用程序的配置信息。Spring Boot提供了简单而强大的功能,可以轻松地加载各种类型的配置文件,并将其映射到Java对象中。通过使用@ConfigurationProperties注解,或者使用@Value注解从配置文件中读取属性值。
425 0
|
16天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
36 8
|
2月前
|
Java Spring
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问
本文介绍了Spring Boot中静态资源的访问位置、如何进行静态资源访问测试、自定义静态资源路径和静态资源请求映射,以及如何处理自定义静态资源映射对index页面访问的影响。提供了两种解决方案:取消自定义静态资源映射或编写Controller来截获index.html的请求并重定向。
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问
|
25天前
|
JavaScript 前端开发 Java
SpringBoot_web开发-webjars&静态资源映射规则
https://www.91chuli.com/ 举例:jquery前端框架
17 0
|
25天前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
26 0
|
3月前
|
Java Spring
Spring Boot实战:静态资源无法访问
Spring Boot实战:静态资源无法访问
72 0
|
4月前
|
Java
自主定义访问路径-----SpringBoot自主定义静态资源访问路径的方法
自主定义访问路径-----SpringBoot自主定义静态资源访问路径的方法
|
5月前
|
搜索推荐 前端开发 JavaScript
SpringBoot静态资源访问控制和封装集成方案
该文档描述了对基于SpringBoot的项目框架进行优化和整合的过程。原先采用前后端分离,后端兼做前端,但随着项目增多,升级维护变得复杂。因此,决定整合后台管理页面与后端代码,统一发布。设计上,框架包含后台管理资源,项目则配置具体业务页面,项目可通过覆盖框架资源实现个性化。关键步骤包括:自定义静态资源访问路径、解决图标与字体文件访问问题、设定自定义欢迎页面和页面图标,以及确保项目能正确访问框架静态资源。通过扫描jar包、解压和拷贝资源到项目目录,实现了框架静态资源的动态加载。此外,调整静态资源访问优先级,保证正确加载。最终实现支持jar和war包的项目结构优化。
111 4
|
5月前
|
缓存 前端开发 JavaScript
Spring Boot中如何处理静态资源
Spring Boot中如何处理静态资源
下一篇
无影云桌面