Spring @WebFilter生产环境报404,本地运行正常求排查建议
结合你提供的代码和问题描述,我整理了几个针对性的排查点,你可以逐一验证:
1. 检查过滤器是否正确放行请求
这是最容易忽略的核心点!看你贴出的MyFilter代码,doFilter方法里没有调用chain.doFilter(httpRequest, httpResponse);——这行代码是让请求继续流转到后续Servlet或过滤器的关键步骤。如果没有它,请求会被过滤器直接拦截终止,DispatcherServlet根本没机会处理请求,自然返回404。
你说本地运行正常,大概率是本地代码里有这行但粘贴时遗漏了,或者本地环境有特殊配置绕过了这个问题,但生产环境没有。先补上这行代码再试:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 你的SSO逻辑代码... // 必须调用这行,让请求继续往下走 chain.doFilter(httpRequest, httpResponse); }
2. 排查过滤器注册方式的冲突
你代码里同时存在两种过滤器注册的可能性:@WebFilter注解和AppInitializer中注释掉的container.addFilter。生产环境的Servlet容器(比如Tomcat)对注解扫描和代码注册的处理逻辑可能和本地不同,容易引发冲突:
- 建议只保留一种注册方式:要么用
@WebFilter,确保AppConfig上添加了@ServletComponentScan(用来扫描注解类);要么在AppInitializer中明确注册过滤器并指定顺序,避免自动扫描的不确定性:// 在AppInitializer的onStartup方法中添加 FilterRegistration.Dynamic accessFilter = container.addFilter("accessFilter", AccessFilter.class); accessFilter.addMappingForUrlPatterns(null, false, "/*"); accessFilter.setOrder(1); // 设置顺序,确保在DispatcherServlet之前执行 - 另外,注意生产环境的web.xml(如果存在)是否设置了
metadata-complete="true",这会禁用Servlet 3.0+的注解扫描,导致@WebFilter失效。
3. 验证过滤器是否在生产环境正常初始化
你提到生产环境中doFilter的代码完全不执行,那先确认过滤器的init方法有没有被调用:
- 把
init里的System.out.println换成正式的日志输出(比如SLF4J),因为生产环境通常不会输出控制台日志,你可能看不到初始化信息。 - 在
init方法中添加异常捕获,检查SSOHelper的初始化是否在生产环境抛出异常:public void init(FilterConfig filterConfig) throws ServletException { try { // 用日志框架输出,比如log.info("AccessFilter initialized"); ssoHelper = new SSOHelper(); // 验证SSOHelper是否初始化成功 if (ssoHelper == null) { throw new ServletException("SSOHelper initialization failed"); } } catch (Exception e) { // 打印异常栈 e.printStackTrace(); throw new ServletException("Failed to initialize AccessFilter", e); } }
如果init方法抛出异常,过滤器会无法正常注册,请求处理时就会出现异常或404。
4. 检查生产环境的上下文路径差异
本地和生产环境的项目上下文路径可能不同(比如本地是根路径/,生产环境是/my-app),如果你的SSO逻辑中处理跳转、回调URL时没有考虑上下文路径,可能会导致跳转后路径错误,返回404。
可以在doFilter中打印请求的完整URL和上下文路径:
System.out.println("Request URL: " + httpRequest.getRequestURL()); System.out.println("Context Path: " + httpRequest.getContextPath());
对比本地和生产环境的输出,确认路径处理是否正确。
5. 缩小过滤器的拦截范围试试
你当前的过滤器拦截/*,会覆盖所有请求(包括静态资源、JS/CSS、HTML等),生产环境的静态资源可能由容器直接处理,过滤器拦截后可能干扰正常的资源访问。可以先把urlPattern改成只拦截业务请求(比如/api/*),看是否还会出现404,以此判断是不是拦截范围过大导致的问题。
内容的提问来源于stack exchange,提问作者Dixyantar Panda

