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

Spring Boot中Filter类获取会话级UserContext对象遇阻求解决方案

解决Spring Boot Filter中无法获取Session Scope Bean的问题

针对你遇到的「Filter中获取@Scope("session")的UserContext时提示‘Scope 'session' is not active for the current thread’」的问题,以下是几个可行的解决思路:

1. 手动激活会话作用域再获取Bean

Spring Boot中会话作用域默认在DispatcherServlet处理请求时才会激活,Filter阶段直接调用会报错。可以手动触发会话作用域的激活:

public class YourFilter implements Filter {
    private WebApplicationContext applicationContext;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        ServletRequestAttributes requestAttributes = new ServletRequestAttributes(httpRequest);
        RequestContextHolder.setRequestAttributes(requestAttributes);

        SessionScope sessionScope = applicationContext.getBean(SessionScope.class);
        try {
            // 激活会话作用域
            sessionScope.startScope();
            // 此时可以正常获取UserContext
            UserContext userContext = applicationContext.getBean(UserContext.class);
            // 执行你的业务逻辑
        } finally {
            // 关闭作用域并清理上下文,避免线程污染
            sessionScope.stopScope();
            RequestContextHolder.resetRequestAttributes();
        }

        chain.doFilter(request, response);
    }
}

2. 调整Filter执行顺序,让它在Spring会话过滤器之后运行

Spring的SessionRepositoryFilter(默认或Redis缓存会话时都会用到)负责初始化会话上下文,你的Filter需要在它之后执行才能获取到激活的会话作用域。可以通过配置Filter的order实现:

方式一:配置类注册Filter时指定Order

@Configuration
public class FilterRegistrationConfig {
    @Bean
    public FilterRegistrationBean<YourFilter> registerYourFilter() {
        FilterRegistrationBean<YourFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new YourFilter());
        registrationBean.addUrlPatterns("/*");
        // SessionRepositoryFilter的默认order是-2147483598,设为比它大的值即可保证在其后执行
        registrationBean.setOrder(-2147483597);
        return registrationBean;
    }
}

方式二:使用@Order注解(配合@WebFilter+@ServletComponentScan)

@WebFilter(urlPatterns = "/*")
@Order(-2147483597)
public class YourFilter implements Filter {
    // ... 实现你的业务逻辑
}

调整顺序后,你的Filter会在会话上下文初始化完成后执行,就能正常获取Session Scope的Bean了。

3. 绕过Spring作用域,直接操作HttpSession

如果不想依赖Spring的会话作用域管理,可以直接将UserContext存入HttpSession,在Filter中直接读取:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpSession session = httpRequest.getSession();
    
    UserContext userContext = (UserContext) session.getAttribute("userContext");
    if (userContext == null) {
        // 若不存在则初始化,可通过Spring容器获取实例
        userContext = applicationContext.getBean(UserContext.class);
        session.setAttribute("userContext", userContext);
    }
    
    // 使用userContext处理业务
    chain.doFilter(request, response);
}

这种方式更直接,彻底避免了Spring作用域激活时机的问题,也能兼容不同Web容器。

另外需要说明:DelegatingFilterProxy只是让Filter被Spring容器管理,但不会改变会话作用域的激活时机;@EnableRedisHttpSession仅负责将会话数据持久化到Redis,同样不影响作用域的激活逻辑,所以这两个配置无法解决你的核心问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:12:46