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

能否设置OpenEntityManagerInView执行顺序使其优先于所有自定义过滤器?

根本原因

OpenEntityManagerInViewInterceptor 是 Spring MVC 层面的拦截器,只有请求进入 DispatcherServlet 后才会触发执行,天然晚于所有 Servlet 过滤器的执行时机,因此调整自定义过滤器的 @Order 注解无法让拦截器提前到过滤器之前运行。
你之前使用 @Order(Ordered.LOWEST_PRECEDENCE) 无效还有两个额外原因:一是 Ordered.LOWEST_PRECEDENCE 对应最大的优先级数值,代表优先级最低,只会让你的过滤器更晚执行但依旧在拦截器之前;二是不同层面的组件(过滤器、MVC拦截器)的Order配置互不生效。


推荐解决方案:改用过滤器级别的EntityManager生命周期管理

将默认的 OpenEntityManagerInViewInterceptor 替换为同功能的 OpenEntityManagerInViewFilter,后者是Servlet过滤器级别的实现,可以通过调整优先级保证在所有自定义过滤器之前执行,具体操作步骤如下:

  1. 关闭默认的拦截器自动配置
    在 application 配置文件中添加配置:
spring.jpa.open-in-view=false
  1. 手动注册OpenEntityManagerInViewFilter并设置最高优先级
@Configuration
public class FilterConfig {
    @Bean
    public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
        return new OpenEntityManagerInViewFilter();
    }

    @Bean
    public FilterRegistrationBean<OpenEntityManagerInViewFilter> emFilterRegistration() {
        FilterRegistrationBean<OpenEntityManagerInViewFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(openEntityManagerInViewFilter());
        // 设置最高优先级,保证最先执行
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        registration.addUrlPatterns("/*");
        return registration;
    }
}
  1. 调整自定义AuthFilter的优先级
    给你的AuthFilter设置大于Ordered.HIGHEST_PRECEDENCE的Order值即可,比如:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
public class AuthFilter extends OncePerRequestFilter {
    // 原有逻辑不变
}

额外优化建议

完成上述配置后,你可以去掉AuthFilter上的@Transactional注解:此时请求进入AuthFilter时,OpenEntityManagerInViewFilter已经完成EntityManager的初始化并绑定到当前线程,Service层的@Transactional会直接复用已有的EntityManager,事务提交后不会关闭EntityManager,EntityManager会在整个请求结束后由OpenEntityManagerInViewFilter统一关闭,彻底避免两次创建关闭会话的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:54:03