在SpringBoot项目中,当静态文件路径与接口路径冲突的时候,SpringBoot是如何处理请求的呢?虽然这种情况很少见,并且也强烈不建议定义与静态文件路径相同的接口,但是也还是来分析一下。举例下面的例子:
1、创建静态文件和接口
1、静态文件
2、接口
@RestController
public class SysUserController {
@RequestMapping("/user.html")
public String test(){
return "这是接口";
}
}
测试结果如下:
可以看到,对于静态文件路径与接口路径冲突的情况,SpringBoot先判断是不是接口,然后再判断是不是静态文件。为什么会这样呢,我们原理分析一下。
2、原理分析
我们知道,不管是接口还是静态文件,所有的请求都必须经过DispatcherServlet,我们就从DispatcherServlet入手。
1、DispatcherServlet#doDispatch
2、DispatcherServlet#getHandler
重点就在于getHandler方法,在该方法中会遍历依次查找能够处理该请求的Handler。而RequestMappingHandlerMapping(支持@RequestMapping带注释的方法),SimpleUrlHandlerMapping(维护对处理程序的 URI 路径模式的显式注册,支持静态文件请求),并且RequestMappingHandlerMapping在SimpleUrlHandlerMapping前面,所以就会先判断是不是接口,然后再判断是不是静态文件。
3、解决方式(不建议)
因为静态文件路径与接口路径冲突的情况是不应该出现的,我们应该去避免出现。当然也可以使用下面的方法解决:
import org.springframework.core.annotation.Order;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
@Component("DispatcherServlet")
@Order
public class MyDispatcherServlet extends DispatcherServlet {
private static final List<String> STATIC_PATH= Arrays.asList(".html", ".css", ".js", ".jpg", ".png");
/**
* 覆盖getHandler方法
*/
@SuppressWarnings("NullableProblems")
@Override
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (String path : STATIC_PATH) {
// 匹配上 直接调用 SimpleUrlHandler 跳去静态资源
if (request.getServletPath().endsWith(path) ) {
List<HandlerMapping> handlerMappings = this.getHandlerMappings();
assert handlerMappings != null;
for (HandlerMapping handlerMapping : handlerMappings) {
if ( handlerMapping.getClass() == SimpleUrlHandlerMapping.class ) {
return handlerMapping.getHandler(request);
}
}
}
}
return super.getHandler(request);
}
}