OmniFaces @ViewScoped Bean离开页面时@PreDestroy方法未调用且报403错误
解决OmniFaces @ViewScoped @PreDestroy不触发的问题
核心原因
你遇到的403错误是Spring Security拦截了OmniFaces发送的卸载请求,而非HTTP协议的问题(sendBeacon在HTTP环境下完全可以正常工作)。标准JSF的javax.faces.view.ViewScoped本身不支持页面卸载时触发@PreDestroy,因为它的销毁逻辑依赖JSF视图的服务器端生命周期,用户主动离开页面时框架无法感知,所以只能依赖OmniFaces的实现。
解决步骤
1. 放行OmniFaces卸载请求路径
在Spring Security配置中,添加规则允许访问OmniFaces的卸载端点/omnifaces.unload(这是OmniFaces处理视图销毁请求的固定路径)。
如果使用Java配置:
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/omnifaces.unload").permitAll() // 放行卸载请求 .anyRequest().authenticated(); // 其他配置... } }
如果使用XML配置:
<security:http> <security:intercept-url pattern="/omnifaces.unload" access="permitAll"/> <security:intercept-url pattern="/**" access="isAuthenticated()"/> <!-- 其他配置 --> </security:http>
2. 确认OmniFaces配置正确性
确保项目中OmniFaces的jar包已正确引入,且使用@ViewScoped的页面已自动加载OmniFaces的unload脚本(OmniFaces会自动注入该脚本,无需手动引入)。
3. 验证请求状态
修改配置后重启应用,测试页面卸载场景:
- 打开浏览器开发者工具的网络面板
- 离开页面时,检查是否有POST请求到
/omnifaces.unload且返回200状态码 - 此时服务器控制台应输出
Destroying view scoped desktop bean
额外说明
- 标准JSF的
javax.faces.view.ViewScoped无法实现页面卸载触发@PreDestroy,它的销毁时机仅为视图被JSF框架标记为过期(如会话超时、导航到其他视图且原视图被销毁),不覆盖用户主动关闭页面或跳转的场景。 - 若问题仍存在,可检查OmniFaces版本与MyFaces的兼容性(你当前使用的OmniFaces 2.7.18和MyFaces 2.3.10是兼容的),或排查是否有其他过滤器拦截了请求。
内容的提问来源于stack exchange,提问作者scholt
相关产品推荐
相关产品推荐

