spring boot 2.x静态资源会被HandlerInterceptor拦截的原因和解决方法
在spring boot 1.5.x中,resources/static目录下的静态资源可以直接访问,并且访问路径上不用带static,比如静态资源放置位置如下图所示:

那么访问静态资源的路径可以是:
当有配置自定义HandlerInterceptor拦截器时,请求以上静态资源路径不会被拦截。自定义HandlerInterceptor拦截器源码如下:
package com.itopener.demo.config; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class LoginRequiredInterceptor extends HandlerInterceptorAdapter { private final Logger logger = LoggerFactory.getLogger(LoginRequiredInterceptor.class); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info(request.getRequestURI());
return super.preHandle(request, response, handler);
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.info(request.getRequestURI());
super.afterCompletion(request, response, handler, ex);
}
}
配置如下:
package com.itopener.demo.config; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class); @Override
public void addInterceptors(InterceptorRegistry registry) {
logger.info("add interceptors");
registry.addInterceptor(new LoginRequiredInterceptor());
} }
访问静态资源时路径上不用加static目录:

当spring boot版本升级为2.x时,访问静态资源就会被HandlerInterceptor拦截

这样对于利用HandlerInterceptor来处理访问权限或其他相关的功能就会受影响,跟踪源码查看原因,是因为spring boot 2.x依赖的spring 5.x版本,相对于spring boot 1.5.x依赖的spring 4.3.x版本而言,针对资源的拦截器初始化时有区别,具体源码在WebMvcConfigurationSupport中,spring 4.3.x源码如下:
/**
* Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
* resource handlers. To configure resource handling, override
* {@link #addResourceHandlers}.
*/
@Bean
public HandlerMapping resourceHandlerMapping() {
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
this.servletContext, mvcContentNegotiationManager());
addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
if (handlerMapping != null) {
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
// 此处固定添加了一个Interceptor
handlerMapping.setInterceptors(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
handlerMapping.setCorsConfigurations(getCorsConfigurations());
}
else {
handlerMapping = new EmptyHandlerMapping();
}
return handlerMapping;
}
而spring 5.x的源码如下:
/**
* Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
* resource handlers. To configure resource handling, override
* {@link #addResourceHandlers}.
*/
@Bean
public HandlerMapping resourceHandlerMapping() {
Assert.state(this.applicationContext != null, "No ApplicationContext set");
Assert.state(this.servletContext != null, "No ServletContext set"); ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
this.servletContext, mvcContentNegotiationManager(), mvcUrlPathHelper());
addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
if (handlerMapping != null) {
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
// 此处是将所有的HandlerInterceptor都添加了(包含自定义的HandlerInterceptor)
handlerMapping.setInterceptors(getInterceptors());
handlerMapping.setCorsConfigurations(getCorsConfigurations());
}
else {
handlerMapping = new EmptyHandlerMapping();
}
return handlerMapping;
} /**
* Provide access to the shared handler interceptors used to configure
* {@link HandlerMapping} instances with. This method cannot be overridden,
* use {@link #addInterceptors(InterceptorRegistry)} instead.
*/
protected final Object[] getInterceptors() {
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
// 此处传入新new的registry对象,在配置类当中设置自定义的HandlerInterceptor后即可获取到
addInterceptors(registry);
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
this.interceptors = registry.getInterceptors();
}
return this.interceptors.toArray();
}
从源码当中可以看出,使用spring 5.x时,静态资源也会执行自定义的拦截器,因此在配置拦截器的时候需要指定排除静态资源的访问路径,即配置改为如下即可:
package com.itopener.demo.config; import java.util.Arrays; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /**
* @author fuwei.deng
* @date 2018年4月13日 下午3:32:54
* @version 1.0.0
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer { private final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class); @Override
public void addInterceptors(InterceptorRegistry registry) {
logger.info("add interceptors");
registry.addInterceptor(new LoginRequiredInterceptor()).excludePathPatterns(Arrays.asList("/views/**", "/res/**"));
}
}
这样就可以和spring boot 1.5.x一样的方式使用了。不过从源码当中可以看出,每个静态资源的请求都会被自定义Interceptor拦截,只是通过访问路径判断后不会执行拦截器的内容,所以spring 5.x相对于spring 4.3.x而言,这部分处理的性能会更低一些
说明:
本文中测试使用的具体版本:
spring-boot-1.5.3.RELEASE(相对应的spring版本是spring-webmvc-4.3.8.RELEASE)
spring-boot-2.0.1.RELEASE(相对应的spring版本是spring-webmvc-5.0.5.RELEASE)
关于配置类,在spring boot 2.x已经改为最低支持jdk8版本,而jdk8中的接口允许有默认实现,所以已经废弃掉WebMvcConfigurerAdapter适配类,而改为直接实现WebMvcConfigurer接口
spring boot 2.x静态资源会被HandlerInterceptor拦截的原因和解决方法的更多相关文章
- Spring Boot实战:静态资源处理
前两章我们分享了Spring boot对Restful 的支持,不过Restful的接口通常仅仅返回数据.而做web开发的时候,我们往往会有很多静态资源,如html.图片.css等.那如何向前端返回静 ...
- Spring Boot 中的静态资源到底要放在哪里?
当我们使用 SpringMVC 框架时,静态资源会被拦截,需要添加额外配置,之前老有小伙伴在微信上问松哥Spring Boot 中的静态资源加载问题:"松哥,我的HTML页面好像没有样式?& ...
- Spring Boot中的静态资源文件
Spring Boot中的静态资源文件 1.SSM中的配置 2.Spring Boot 中的配置 2.1 整体规划 2.2 源码解读 2.3 自定义配置 2.3.1 application.prope ...
- spring boot默认访问静态资源
演示spring boot默认可以直接访问静态资源的2种方法: 第一种:在src/main/resources资源目录下创建一个名为"static"的文件夹(该文件夹的名称是规定死 ...
- spring boot 2.0 + 静态资源被拦截,怎么办?
问题描述:使用springboot 2.0后,按照springboot 1.5版本(以下简称旧版)的方式去配置项目.结果发现静态资源访问不到了,本文对此情况分析.处理 项目结构: 直接上图 如果是在旧 ...
- 【spring boot】7.静态资源和拦截器处理 以及继承WebMvcConfigurerAdapter类进行更多自定义配置
开头是鸡蛋,后面全靠编!!! ======================================================== 1.默认静态资源映射路径以及优先顺序 Spring B ...
- (4)Spring Boot Web开发---静态资源
文章目录 对静态资源的映射规则 模板引擎 Thymeleaf 使用 & 语法 使用之前将的快速创建项目的方法,勾选我们需要的场景,这里我需要 web --> web.sql --> ...
- spring boot 配置虚拟静态资源文件
我们实现的目的是:通过spring boot 配置静态资源访问的虚拟路径,可实现在服务器,或者在本地通过:http://ip地址:端口/资源路径/文件名 ,可直接访问文件 比如:我们本地电脑的:E: ...
- spring boot 项目 mvn clean install 报 "Unable to find main class" 的解决方法
按照步骤来总会解决的 检查pom.xml中是否加入了spring boot maven插件 <build> <plugins> <plugin> <group ...
随机推荐
- scrapy新版本特性
1:在spider中返回一个自定义的字典,老版本中需要先定义一个Item,填充后再返回一个对象 新版本中可以直接返回一个字典 2:Per-spider settings 为每个spider进行单独设 ...
- vue之axios使用
axios是vue-resource后出现的Vue请求数据的插件.vue更新到2.0之后,作者尤大就宣告不再对vue-resource更新,而是推荐的axios. 下面我们来使用axios npm i ...
- IOS 上传项目到github 终端操作
1.创建github账号 2.创建秘钥 3.Github配置秘钥 4.上传文件 复制保存网址 终端操作,如果没有ssh,自行安装 GitHub配置秘钥 克隆github上创建的项目 将自己的本地项目, ...
- 【BZOJ4008】【HNOI2015】亚瑟王 [期望DP]
亚瑟王 Time Limit: 20 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 小 K 不慎被 LL 邪教洗脑了,洗 ...
- bzoj 2748 DP
比较裸的背包,w[i][j]代表到第I个操作的时候音量j能不能达到,然后转移就行了. /******************************************************** ...
- KM算法讲解
对于二分图,我们可以用匈牙利来求出来最大匹配,但是如果给定每条边一个权值,我们要求这张图的最大匹配最大(小)权,单纯的用匈牙利就没法解决了,当然用费用流也可以做,但是代码较长,在处理完全二分图的时候时 ...
- linux驱动学习(二) Makefile高级【转】
转自:http://blog.csdn.net/ghostyu/article/details/6866863 版权声明:本文为博主原创文章,未经博主允许不得转载. 在我前一篇写的[ linux驱动学 ...
- Codeforces 270E Flawed Flow 网络流问题
题意:给出一些边,给出边的容量.让你为所有边确定一个方向使得流量最大. 题目不用求最大流, 而是求每条边的流向,这题是考察网络流的基本规律. 若某图有最大,则有与源点相连的边必然都是流出的,与汇点相连 ...
- Makefile PHONY
case 1: Makefile clean: rm a environment_1 : There is only file a $ make clean clean a environment_2 ...
- 【bzoj1013】球形空间产生器
高斯消元…… 看完线代那一节之后感觉真的是……naive! 线代大法好. #include<bits/stdc++.h> using namespace std; ; int n; ][] ...