1 静态资源到存放路径
实例:
那么这是如何进行通过链接进行访问,下面是资源配置方法,进行路径拦截之后找到对应的文件路径
package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
/**
* 通用配置
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
/** swagger配置 */
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/METAINF/resources/webjars/");
//当时写的好像是上传的路径然后进行访问
registry.addResourceHandler("/police" + "/**").addResourceLocations("file:" + System.getProperty("user.home")+"/police/fileInfo/");
registry.addResourceHandler( "/static"+"/**").addResourceLocations("classpath:/static/");
}
/**
* 自定义拦截规则
*/
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
}
/**
* 跨域配置
*/
@Bean
public CorsFilter corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置访问源地址
config.addAllowedOrigin("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 对接口配置跨域设置
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
访问本地文件
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/pdf" + "/**").addResourceLocations("file:" + System.getProperty("user.home")+"/lcls/fileInfo/");
}
C:\Users\Administrator\lcls\fileInfo
上面的例子应该可以快速的进行修改,下面进行原理讲解当使用SpringMVC框架访问静态资源时,静态资源会被拦截,需要添加额外配置。搭建SSM环境时,可以通过<mvc:resources />
节点来配置不拦截静态资源,代码如下:
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/html/**" location="/html/"/>
这是一种Ant风格的路径匹配符,/**
表示可以匹配任意层级的路径,所以上面的代码可以简化为:
<mvc:resources mapping="/**" location="/"/>
上面这种配置是通过xml文件实现的,而且通俗易懂,其实在Java中也可以通过Java代码实现,如果通过Java代码实现,可以自定义一个类,并且让其集成WebMvcConfigurationSupport
即可,代码如下:
@Configuration
@ComponentScan(basePackages = "com.mango.javassm")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
}
上面代码中,其实就是重写了WebMvcConfigurationSupport
中的addResourceHandlers
方法,并且在该方法中配置静态资源访问路径。上面两种配置方式实现的效果是一样的。
上面介绍的两种方式都是传统的解决方案,在SpringBoot中,配置方式和SSM相同,不同的是SpringBoot是自动化配置。正是这些自动化配置能大大的节省开发人员的代码,自然而然也就降低了出错率。(写的越多,bug越多)
通配符 | 说明 |
---|---|
? | 匹配任意一个字符 |
* | 匹配任意字符(包括0个) |
** | 匹配任意层路径(包括0个) |
常见Ant风格场景:
- Spring资源加载:
classpath:/static/
- SpringMVC的URL映射:
@GetMapping("/hello")
- Spring注解扫描:
<mvc:resources mapping="/**" location="/"/>
【SpringBoot中的配置】
创建SpringBoot项目时,通常都是在https://start.spring.io/
网站进行创建的,其实通过IDEA来创建也是访问这个网站,创建后项目中默认都会存在resources/static
目录,大家也都知道静态资源放到这个目录下,就可以直接进行访问了。除了这个目录还有没有其他目录可以放呢?为什么放在这个目录下就可以直接进行访问了呢?接下来就围绕这个问题进行挖掘。
在SpringBoot中,默认情况下,共有5个地方可以放静态资源,分别是:
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public/
- /
其实前面的四个目录都容易理解,分别是对应resources
下不同的目录,但是第5个中的/
是啥呢?
我们都知道,在 Spring Boot 项目中,默认是没有 webapp
这个目录的,当然我们也可以自己手动进行添加(例如在需要使用jsp的时候),这里第5个/
其实就是表示 webapp
目录中的静态资源也不被拦截。如果同一个文件分别出现在五个目录下,那么优先级也是按照上面列出的顺序来进行访问的。
虽然默认情况下提供了5个访问目录,但第5个目录很少会使用到。由于创建项目时,默认给我们创建了classpath:/static/
,一般情况下,我们只需要把我们的静态资源放到该目录下即可,不需要额外创建目录,例如:我在classpath:/static/
目录下放了一个hello.js
文件,那么访问该js文件的路径是:
http://localhost:8080/hello.js
值得注意的是,请求地址中并不需要 static,如果加上了static反而多此一举会报404错误。很多人会觉得奇怪,为什么不需要添加 static呢?资源明明放在 static 目录下。其实这个效果很好实现,例如:在SSM配置中,我们的静态资源拦截配置如果是下面这样:
<mvc:resources mapping="/**" location="/static/"/>
如果是这样配置的话,我们的请求路径是http://localhost:8080/hello.js
,实际上系统会去 /static/hello.js
下去查找相关的静态资源。
回到SpringBoot中,既然它的原理和SSM相同,所以这里就不难理解了。
3 源码解读学习新的东西,最准确的方式莫过于阅读源码了,下面我们通过源码来看看SpringBoot中静态资源是如何配置的。
首先,我们在WebMvcAutoConfiguration
类中看到SpringMVC自动化配置的相关内容,找到了静态资源拦截的配置,如下:
其实从上面这段标出的内容可以看出,这里对静态资源的定义和前面提到的Java配置SSM非常相似。其中,this.mvcProperties.getStaticPathPattern()
方法对应的值就是"/**"
,this.resourceProperties.getStaticLocations()
方法返回了一个String[]数组,其中包含了共4个位置,它们分别是:"classpath:/META-INF/resources/"
、"classpath:/resources/"
、"classpath:/static/"
、"classpath:/public/"
,然后在getResourceLocations
方法中的SERVLET_LOCATIONS
又添加了"/"
,因此这里一共返回了5个位置,其中"/"
表示webapp
目录,即webapp
目录下的静态资源也可直接访问。静态资源匹配路径按照定义路径优先级依次降低,前面4个不难理解,至于为什么"/"
排在最后,我想大家仔细看下源码就能明白。
如此看来,大家应该明白了为什么SpringBoot中默认支持5个静态资源位置的配置了,同时也明白了为什么访问静态资源的请求路径中不用添加/static
了,因为路径映射中已经自动添加了。
这里给提供两种方式,一种是通过配置文件实现,另一种是通过Java类来实现,不管是哪种,实现的效果都是相同的。
【application.properties】
spring.resources.static-locations=classpath:/mango
spring.mvc.static-path-pattern=/**
注:上面classpath:/mango
中的mango
是我在resources
下创建的一个目录。
【Java类】
当然,在SpringBoot中也可以通过Java代码来定义,和用Java来配置SSM方式比较类似,如下:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/mango/");
}
}
这段代码比较简单,之前也讲过,这里就不再啰嗦了。
5 总结这里需要注意的是,很多人用了 Thymeleaf
模板引擎之后,会将静态资源也放在 resources/templates
目录下,注意,templates
目录并不是静态资源目录,它是一个放页面模板的位置(你看到的 Thymeleaf
模板虽然后缀为 .html
,其实并不是静态资源)。