Spring REST API移除URL后缀.do的问题解决探索
问题:Spring Boot 3.0.0升级后.do后缀导致PathVariable参数异常
将项目从Spring Boot 2.2.4.RELEASE升级至3.0.0,并把web.xml配置转为Java代码。原web.xml中的Servlet映射配置:
<servlet-mapping> <servlet-name>ServletName</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
转换后的Java代码如下:
@Configuration @Slf4j public class MyServlet implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) { ServletRegistration.Dynamic servlet = servletContext.addServlet("ServletName", new DispatcherServlet(new AnnotationConfigWebApplicationContext())); servlet.setLoadOnStartup(1); servlet.setAsyncSupported(true); servlet.addMapping("*.do"); } }
调用POST /api/private/smartphone.do接口时,该接口的映射代码为:
@PostMapping(value = "/private/{type}", produces = MediaType.APPLICATION_JSON_VALUE) public JsonResponse getSmartphones(@PathVariable SType type) { ... }
发现.do后缀未被移除,PathVariable参数type的值为"smartphone.do",不符合预期(SType是枚举,仅包含smartphone、laptop、appliances)。
尝试过的方案
- 自定义路径匹配器:实现WebMvcConfigurer
@Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setPathMatcher(new CustomPathMatcher()); } private static class CustomPathMatcher extends AntPathMatcher { @Override public boolean match(String pattern, String path) { if (path.endsWith(".do")) { path = path.substring(0, path.length() - 3); } return super.match(pattern, path); } }
- 继承HttpServlet处理请求路径
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { var req = request.getRequestURI(); if(req.endsWith(".do")) { request.getRequestDispatcher(req.substring(0, req.length() - 3)); } }
- 配置RequestMappingHandlerMapping Bean
@Bean public HandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping(); mapping.setUseSuffixPatternMatch(false); return mapping; }
可行的解决方法
更新1:添加拦截器
实现拦截器处理路径后缀:
public class ExtensionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String path = request.getRequestURI(); if (path.endsWith(".do")) { String newPath = path.substring(0, path.length() - 3); request.getRequestDispatcher(newPath).forward(request, response); return false; } return true; } }
通过WebMvcConfigurer注册拦截器:
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ExtensionInterceptor()).addPathPatterns("/private/**"); }
更新2:修改接口映射路径
直接调整接口的映射注解,指定.do后缀:
@PostMapping("/private/{type}.do")
内容的提问来源于stack exchange,提问作者Jakkins
相关产品推荐
相关产品推荐

