一、遇到的问题
由于对旧的spring项目改造升级为spring boot项目,发现以前springmvc中配置的 *.do 拦截请求匹配,放到spring boot中不生效,所以跟踪源码查找路径无法匹配原因。
二、解决前配置方式(spring boot)
1、 在yml配置文件中开启后缀匹配。
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# 使用后缀匹配
use-suffix-pattern: true
use-registered-suffix-pattern: true
2、 定义springmvc 配置类
package com.example.demo;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
/**
* @author : xlw
* @since : 2023-08-11 10:02
* Config
*/
@Configuration
public class Config {
@Bean
public DispatcherServlet dispatcherServlet(){
return new DispatcherServlet();
}
@Bean
public ServletRegistrationBean servletRegistrationBean(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean<DispatcherServlet> bean = new ServletRegistrationBean(dispatcherServlet);
bean.addUrlMappings("*.do");
return bean;
}
}
3、 配置测试类
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : xlw
* @since : 2023-08-11 11:00
* TestController
*/
@RestController
public class TestController {
@GetMapping("/test")
public String test(){
return "测试请求成功";
}
}
4、然后在浏览器地址栏访问出现404
三、使用问题解决方案
在上述“二”配置的基础上添加媒体类型注册:注册.do 扩展后缀即可
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author : xlw
* @since : 2023-08-11 13:44
* Mather
*/
@Configuration
public class Mather implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.mediaType(".do", MediaType.ALL);
}
}
四、问题跟踪
- 找到请求映射匹配处理入口类方法AbstractHandlerMapping.getHandler
- 进入org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal方法
- 进入org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
继续看org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#addMatchingMappings
- 进入org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getMatchingMapping
- 进入org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition
- 在5 中看到与路径匹配相关的,本次解决方案用的是this.patternsCondition.getMatchingCondition(request);
所以进入这个方法org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingCondition
继续进入
继续进入方法 getMatchingPattern
此处看到了关键代码:
- 需要开启后缀匹配:配置文件里面spring.mvc.pathmatch.use-suffix-pattern=true
- 如果fileExtensions 文件扩展不是空,则会走扩展匹配,因为使用springboot后集成默认会找到fileExtensions 里面为.json, .xml 扩展配置,走这个逻辑,没有匹配到.do 所以返回了null, 浏览器界面就出现了404
- 如果fileExtensions 是空,则会走.* 后缀匹配,注:通过跟踪旧的spring项目在springmvc 阶段,fileExtensions 确实是空,能够通过匹配.do 后缀。
- fileExtends 怎么注册自己的扩展信息,则就是当前问题解决问题处理方式,注册了.do 类型,处理所有媒体请求
- 应该还有更优的解决方式…