基于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
相关产品推荐
相关产品推荐

