博客 / 詳情

返回

記SpringBoot升級Tomcat引發的兩類典型問題及解決方案

記SpringBoot升級Tomcat引發的兩類典型問題及解決方案

在SpringBoot項目維護過程中,版本升級是常見操作,但往往會引發一些兼容性問題。本文記錄了將SpringBoot內置Tomcat從8.5.51升級到9.0.75後遇到的兩個典型問題:URL包含雙斜槓//導致404、DELETE請求報HttpRequestMethodNotSupportedException,並給出對應的解決方案和原理分析。

一、URL包含//導致404問題

問題現象

Tomcat版本升級至9.0.75後,前端點擊菜單出現404錯誤,排查發現請求URL中存在連續的雙斜槓(如/api//user/list),將Tomcat回退到8.5.51後問題消失。

問題原因

Tomcat 9.x對URL的規範化處理邏輯相比8.x更嚴格:

  • Tomcat 8.5.51會自動將URL中的連續斜槓//合併為單斜槓/,因此即使URL拼寫不規範也能正常訪問;
  • Tomcat 9.0.75默認不再自動合併連續斜槓,導致包含//的URL無法匹配後端接口,觸發404錯誤。

解決方案

方案1:統一規範前端菜單URL配置(推薦)

從根源上解決問題,檢查並修正所有菜單、前端請求的URL配置,將所有連續的//替換為單斜槓/
示例:

  • 錯誤URL:/system//menu
  • 修正後:/system/menu

方案2:配置Tomcat允許合併連續斜槓(應急方案)

若暫時無法批量修正URL,可通過配置Tomcat參數恢復8.x的URL處理邏輯:

import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatConfig {
    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers((Connector connector) -> {
            // 開啓URL規範化,合併連續斜槓
            connector.setNormalizeUri(true);
            // Tomcat 9.x新增參數,允許路徑中的連續斜槓
            connector.setAttribute("allowBackSlash", true);
            connector.setAttribute("normalizePath", true);
        });
        return tomcat;
    }
}

二、DELETE請求報HttpRequestMethodNotSupportedException異常

問題現象

前端發起DELETE請求時,後端拋出如下異常:

org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported

問題原因

瀏覽器原生只支持GET和POST請求,前端通常通過form表單+隱藏參數的方式模擬DELETE/PUT請求。SpringBoot中處理該場景的HiddenHttpMethodFilter過濾器默認是關閉的(尤其是高版本SpringBoot),導致POST請求無法被轉換為DELETE請求,進而觸發請求方法不支持的異常。

解決方案

方案1:開啓HiddenHttpMethodFilter(配置文件方式)

application.propertiesapplication.yml中添加配置:

# 開啓HiddenHttpMethodFilter過濾器,支持POST模擬DELETE/PUT請求
spring.mvc.hiddenmethod.filter.enabled=true
spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true

方案2:手動註冊HiddenHttpMethodFilter(代碼方式)

若配置文件方式不生效,可手動註冊過濾器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;

@Configuration
public class WebConfig {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter();
    }
}

前端配合示例

前端需在POST表單中添加_method=DELETE隱藏參數:

<form action="/api/user/1" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <button type="submit">刪除用户</button>
</form>

補充説明

  1. HiddenHttpMethodFilter僅處理Content-Typeapplication/x-www-form-urlencoded的POST請求;
  2. 若前端使用Axios等AJAX工具,可直接設置method: 'DELETE',無需依賴該過濾器;
  3. 過濾器優先級:若項目中有自定義過濾器,需保證HiddenHttpMethodFilter執行順序靠前。

三、總結

  1. Tomcat 9.x對URL規範化更嚴格,需統一規範URL拼寫(避免//),或通過配置恢復8.x的URL處理邏輯;
  2. SpringBoot中模擬DELETE/PUT請求需開啓HiddenHttpMethodFilter,核心配置為spring.mvc.hiddenmethod.filter.enabled=true
  3. 版本升級前建議先做小範圍驗證,重點關注基礎組件(如Tomcat)的行為變更,提前規避兼容性問題。

四、擴展建議

  1. 建立URL規範檢查機制:在前端工程中添加ESLint規則,禁止URL中出現連續斜槓;
  2. 統一請求方式:新項目建議優先使用RESTful API+AJAX(Axios/Fetch),減少表單模擬DELETE/PUT的場景;
  3. 版本兼容:升級依賴前查閲官方變更日誌,重點關注核心組件(Tomcat、Spring框架)的行為變更點。
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.