You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:52:14