SpringBoot静态资源配置详解(下)

静态资源的应用

自定义静态资源外部路径映射

第一种方式:静态资源配置类

在实际开发中,我们可能需要自定义静态资源访问以及上传路径,特别是文件上传,不可能上传的运行的JAR服务中,那么可以通过继承WebMvcConfigurerAdapter来实现自定义路径映射。
application.properties 文件配置:

# 图片音频上传路径配置(win系统自行变更本地路径)
web.upload.path=/home/file/

WechatApplication.java 启动配置:

/**
 * 语音测评后台服务
 * 创建者 柒
 * 创建时间    2018年3月8日
 */
@SpringBootApplication
public class WechatApplication extends WebMvcConfigurerAdapter  {
    
    
    
    private final static Logger LOGGER = LoggerFactory.getLogger(WechatApplication.class);
    
    @Value("${web.upload.path}")
    private String uploadPath;
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/uploads/**").addResourceLocations(
                "file:"+uploadPath);
        LOGGER.info("自定义静态资源目录、此处功能用于文件映射");
    }
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(WechatApplication.class);
        LOGGER.info("语音测评后台服务启动成功");
    }
 
}

第二种方式:在application.properties配置
在application.properties中添加配置:

# 静态文件请求匹配方式
spring.mvc.static-path-pattern=/upload/**
# 修改默认的静态寻址资源目录 多个使用逗号分隔
# spring.web.resources.static-locations = classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/itstyle/
spring.web.resources.static-locations=file:${web.upload-path},file:${web.front-path}

注意:通过spring.mvc.static-path-pattern这种方式配置,会使Spring Boot的默认配置失效,也就是说,/public , /resources 等默认配置不能使用。
配置中配置了静态模式为/upload/**,访问时候就只能通过/upload/xx 来访问。
我们现在可以访问以下路径:

http://localhost:8080/uploads/1.jpg

位置与优先级

位置

spring boot的静态资源:

  • static目录:css、js、图片等
  • templates目录:html页面

优先级

spring boot默认将/**静态资源访问映射到以下目录:

classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources

这四个目录的访问优先级:META-INF/resources > resources > static > public

即:这四个路径下如果有同名文件,则会以优先级高的文件为准。

其对应的配置方法为:application.yml。默认配置如下:

spring:
  web:
    resources:
      static-locations: classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/

其实,它还与application.yml的下边这个配置有关,两者联合起来控制路径

spring:
  mvc:
    static-path-pattern: /**

HTML放置位置的区别

HTML文件放到templates目录下,推荐将html页面放置在templates目录,原因如下:
templates目录下的html页面不能直接访问,需要通过服务器内部进行访问,可以避免无权限的用户直接访问到隐私页面,造成信息泄露。

HTML文件放到static目录下

这样用户可以通过两种方法获得到html页面:

直接访问.html资源
通过controller跳转
就像上边说的一样,当直接访问.html资源时,用户可以访问到无权访问的页面。

templates和static目录都是项目创建时自带的!!!!!!

HTML存放于templates目录(推荐)

步骤1:引入thymeleaf 依赖(视图解析),这里的页面必须通过controller跳转才能访问

<!--访问静态资源-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

步骤2:写一个简单的HTML,放置到templates路径

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>this is title</title>
</head>
<body>
<div>
 这是templates 的demo !!!!!!
</div>
</body>
</html>

步骤3:编写Controller

package com.example.demo.views;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("view")
public class ViewController {
    
    
    @GetMapping("demo")
    public String demo() {
    
    
        return "demo";
    }
}

需要注意:必须使用@Controller,不能使用@RestController。
因为@RestController返回的是 JSON,且不走SpringMVC的视图解析流程,所以跳不到html那里。
测试
在这里插入图片描述

HTML存放于static目录(不推荐)

法1:直接访问.html资源

步骤1:将html放到static目录
在这里插入图片描述

法2:通过controller跳转

步骤1:确保没有thymeleaf依赖

步骤2:将html放置到static路径

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>this is title</title>
</head>
<body>
<div>
    这是static的demo
</div>
</body>
</html>

步骤3:编写controller

package com.example.demo.views;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("view")
public class ViewController {
    
    
    @GetMapping("demo")
    public String demo() {
    
    
        return "/demo.html";
    }
}

注意:返回的字符串前边必须带“/” 。
在这里插入图片描述
说明

也可以如下操作,结果是一样的:

application.yml配置前后缀:
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html

controller这样写:

package com.example.demo.views;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("view")
public class ViewController {
    
    
    @GetMapping("demo")
    public String demo() {
    
    
        return "demo";
    }
}

自己包下的静态资源导入到Springboot中
Springboot,默认的静态资源映射是这样的

spring:
  web:
    resources:
      static-locations: classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/

以下两种方法都会使得Springboot默认的静态资源映射失效
第一种方法
修改成这样子
在这里插入图片描述

spring:
  web:
    resources:
      static-locations: classpath:/

这样就代表我们resources下的都注册到Springboot静态资源下了(templates还是不能直接访问地址,因为他加载了thymeleaf 依赖(视图解析)。

在这里插入图片描述
第二种方法,通过类实现

package com.example.config;
 import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
 
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    
    /**
     * 设置静态资源映射
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    
        log.info("开始进行静态资源映射...");
    registry.addResourceHandler("/AAAtest/**").addResourceLocations("classpath:/AAAtest/");
    }
}

在这里插入图片描述
两种方法都会使得默认配置失效!!!!!

spring:
  web:
    resources:
      static-locations: classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/

静态资源缓存问题

在实际的开发中,我们总是会面临这样一个问题:生产环境有一个js需要优化,优化完成后需要更新到生产,但仅是这样的操作,问题就解决了吗?其实并没有。因为对于一些老用户来说,他们的浏览器已经缓存了你旧版本的js,就算你新版本js上线,对于开发人员来说,清一下缓存就好了,但是你指望用户帮你清除缓存么?这也不太现实。对于此类问题,以前最简单粗暴的方式就是给经常需要变动的js后加一个时间戳,导致页面加载时,每次都要从服务器加载js,这种做法可以解决问题,但是会影响性能。

SpringMVC给我们提供了两种解决方案:内容MD5和版本控制,这两种方案中,版本控制其实和webjars的版本访问机制类似。而MD5的这种方式默认情况下只有在重启项目后才能生效,当然你也可以通过其他方式让每次请求的时候都重新计算内容的MD5进行比对,但是这种方式不推荐,如果静态资源比较大,则会有性能问题。

1、内容MD5清除缓存

#开启内容策略
spring.resources.chain.strategy.content.enabled=true
#内容策略作用的路径
spring.resources.chain.strategy.content.paths=/**

MD5静态内容策略配置比较简单,需要注意的是,如果你在JavaConfig中启动了MVC配置,则在属性文件中配置的策略失效,必须移动至JavaConfig中进行配置。栗子、访问路径

2、版本控制清除缓存

#内容策略,版本控制
spring.resources.chain.strategy.fixed.enabled=true
#版本文件所在位置
spring.resources.chain.strategy.fixed.paths=/js/lib/**
#版本定义
spring.resources.chain.strategy.fixed.version=v12

栗子、访问路径,以下两种方式都支持
/{配置的版本}/js/lib/mymodule.js
/js/lib/mymodule.js
版本控制的配置,有时会由于SpringBoot版本的问题而不生效,需增加如下JavaConfig配置才会生效:

@Configuration
public class ThymeleafConfig {
    
    
    @Bean
    public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
    
    
        return new ResourceUrlEncodingFilter();
    }
}

小结

关于静态的资源的使用就聊这么多,总结一下:
1、静态资源使用默认配置基本能够满足开发需要,建议不要轻易改动;
2、webjars更适合系统基础框架静态资源的打包;
3、内容策略要么统一在JavaConfig中配置,要么统一在属性配置文件配置否则会失效;
4、内容策略版本控制,按照官方文档配置可能不会生效,解决方案就是注入ResourceUrlEncodingFilter组件。

鸣谢

https://blog.csdn.net/qq_33879443/article/details/125797005
https://blog.csdn.net/qq_45470811/article/details/104030242

猜你喜欢

转载自blog.csdn.net/CNCDXX_88/article/details/129935203
今日推荐