SpringBoot2 静态文件路径与接口路径冲突(相同)解决方案

事情是这样的, 最近接手个项目 给它底层从ssm整到springboot2 + mp
由于之前很多xxx.do请求 而我又不想用后缀,
所以就得匹配全部后缀或者无后缀(方法有很多方案自行百度), 然后就狗血的出现了一个问题

 

起因是controller接口的mapping与静态文件路径一样 如下图

 

 

 

 

由于我开了匹配任意后缀功能,
这样当你访问这个html的时候就会被认为是正常的get请求被转发到controller去处理,
说明springboot是先判断是不是请求然后再判断是不是静态文件
我们得给它改改顺序

 

我们都知道springmvc的默认servlet是DispatcherServlet

那就去瞅瞅DispatcherServlet是怎么处理的

 

 继续跟踪

 

 说明实在这一行确定请求的类型的 发现它调用了getHandler方法 继续跟

 

阅读getHandler方法发现它是获取所有handler直接遍历 发现能处理就直接return了
那这样说明在这个this.handlerMappings遍历的时候肯定先找到的是controller层的handler
我们先通过debug看看handlerMappings里有哪些handler

 

debug发现索引1的位置是controller层的handler
而html文件的handler在最后面 叫做SimpleUrlHandlerMapping
我们需要让它这个请求返货SimpleUrlHandlerMapping 而不是RequestMappingHandlerMapping

 

那我们自定义 MyDispatcherServlet 继承 DispatcherServlet 改改它的 getHandler里的逻辑就行了

这是重写的 MyDispatcherServlet

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;

/**
 *  自定义 DispatcherServlet 以支持静态文件路径和api请求路径冲突时先支持静态文件路径
 * @author xudaz
 * @date 2021/6/11
 * @see MyMvcConfig#servletRegistrationBean(com.qjr.amp.common.config.MyDispatcherServlet)
 */
@Component("DispatcherServlet")
@Order
public class MyDispatcherServlet extends DispatcherServlet {

    private static final List<String> STATIC_PATH= Arrays.asList(".html", ".css", ".js", ".jpg", ".png");

    /**
     * Return the HandlerExecutionChain for this request.
     * <p>Tries all handler mappings in order.
     *
     * @param request current HTTP request
     * @return the HandlerExecutionChain, or {@code null} if no handler could be found
     */
    @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);
    }
}
然后还要给springBoot 注册一下 在启动类或者配置类里注册
    /**
     * 设置匹配*.* 后缀请求
     */
    @Bean
    public ServletRegistrationBean<DispatcherServlet> servletRegistrationBean(MyDispatcherServlet dispatcherServlet) {
        ServletRegistrationBean<DispatcherServlet> servletServletRegistrationBean = new ServletRegistrationBean<>(dispatcherServlet);
        servletServletRegistrationBean.addUrlMappings("/");
        return servletServletRegistrationBean;
    }

! 注意 我这里形参的参数类型写的是我自己写的MyDispatcherServlet 这样就能注册上了

效果

能访问了

 

posted on 2022-12-13 17:02  尹镇镇  阅读(580)  评论(0)    收藏  举报