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

基于Jakarta的HandlerInterceptor在Javax环境下无法拦截请求

问题分析与解决方案

问题背景

项目基于Javax栈(如Spring Boot 2.x),但拦截器使用Jakarta库实现,导致请求无法被拦截。拦截器代码及配置如下:

拦截器实现(Jakarta版本)

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import io.opentracing.Tracer;
import io.opentracing.Span;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.DispatcherType;
import org.springframework.http.HttpMethod;

@ControllerAdvice
public class RequestGETInterceptor implements HandlerInterceptor {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private Tracer tracer;

    @Override
    public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
            final Object handler) {

        if (DispatcherType.REQUEST.name().equals(request.getDispatcherType().name())
                && request.getMethod().equals(HttpMethod.GET.name())) {
            Map<String, String> headers = Collections.list(request.getHeaderNames())
                    .stream()
                    .collect(Collectors.toMap(h -> h, request::getHeader));
            Map<String, String> uriVariables = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            if (handler instanceof HandlerMethod) {
                String methodName = ((HandlerMethod) handler).getMethod().getName();
            }

            final Span span = this.tracer.currentSpan();
            this.log.info("{} Request {}", request.getMethod(), span.context().spanId());
        }

        return true;
    }
}

拦截器注册配置

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfigInterceptors implements WebMvcConfigurer {

    @Autowired
    private RequestGETInterceptor getInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getInterceptor);
    }

}

核心矛盾:Javax和Jakarta是两套不兼容的API规范,Spring Boot 2.x依赖Javax.servlet等Javax栈组件,而拦截器使用Jakarta.servlet的类,导致Spring无法识别该拦截器的类型,进而无法触发拦截逻辑。


解决办法

方案1:升级项目到Jakarta栈(推荐)

将项目升级到Spring Boot 3.x及以上版本,该版本全面切换为Jakarta API,与拦截器的依赖完全兼容:

  • 修改项目构建文件(如pom.xml或build.gradle),将Spring Boot版本升级至3.x(例如3.2.0)
  • 替换所有Javax相关依赖为Jakarta版本,例如:
    • 原javax.servlet-api替换为jakarta.servlet:jakarta.servlet-api
    • 原javax.validation:validation-api替换为jakarta.validation:jakarta.validation-api
  • 项目中所有Javax相关导入路径替换为Jakarta,例如javax.servlet.http.HttpServletRequest改为jakarta.servlet.http.HttpServletRequest

方案2:修改拦截器为Javax栈实现

若无法升级项目,将拦截器的Jakarta依赖替换为Javax版本,确保与项目栈一致:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import io.opentracing.Tracer;
import io.opentracing.Span;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.DispatcherType;
import org.springframework.http.HttpMethod;

@ControllerAdvice
public class RequestGETInterceptor implements HandlerInterceptor {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private Tracer tracer;

    @Override
    public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
            final Object handler) {

        if (DispatcherType.REQUEST.name().equals(request.getDispatcherType().name())
                && request.getMethod().equals(HttpMethod.GET.name())) {
            Map<String, String> headers = Collections.list(request.getHeaderNames())
                    .stream()
                    .collect(Collectors.toMap(h -> h, request::getHeader));
            Map<String, String> uriVariables = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            if (handler instanceof HandlerMethod) {
                String methodName = ((HandlerMethod) handler).getMethod().getName();
            }

            final Span span = this.tracer.currentSpan();
            this.log.info("{} Request {}", request.getMethod(), span.context().spanId());
        }

        return true;
    }
}

注意:确保拦截器依赖的所有Servlet相关类均为Javax版本,避免混合导入。

方案3:排查并解决依赖冲突

通过构建工具的依赖分析功能,找出并排除冲突的Jakarta/Javax依赖,确保项目中仅存在一套API:

  • Maven用户执行 mvn dependency:tree,Gradle用户执行 ./gradlew dependencies
  • 查找输出中同时出现javax.servlet和jakarta.servlet的依赖,通过<exclusions>(Maven)或exclude(Gradle)排除其中一套
  • 例如在Maven中排除多余的Jakarta依赖:
<dependency>
    <!-- 存在冲突的依赖 -->
    <groupId>xxx</groupId>
    <artifactId>xxx</artifactId>
    <version>xxx</version>
    <exclusions>
        <exclusion>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

内容的提问来源于stack exchange,提问作者witilongi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 10:37:21