讲师中心 微信公众号

工具推荐

视频效率加速
updream

一键生成高质量推广成片

Laper
Laper

剧本策划到成片协作

剧云
剧云

中文短剧剧本制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

CDI会话生命周期事件拦截指南

雨婷吖_3060

雨婷吖_3060

发布时间:2025-11-22 12:44:21

|

465人浏览过

|

来源于php中文网

原创

cdi会话生命周期事件拦截指南

本文旨在指导开发者如何在CDI应用中有效拦截会话(Conversation)的开始与结束事件。文章解释了直接通过`ProcessAnnotatedType`动态绑定拦截器对`Conversation`类不可行的原因,并提供了一种基于CDI上下文生命周期事件的正确方法。通过观察`@Initialized(ConversationScoped.class)`和`@Destroyed(ConversationScoped.class)`事件,开发者可以优雅地实现对会话生命周期的精确控制和业务逻辑集成。

理解CDI会话与拦截挑战

在CDI(Contexts and Dependency Injection)框架中,会话(Conversation)是一种重要的作用域,它允许状态在一个或多个HTTP请求中保持。开发者有时需要精确地知道会话何时开始和结束,以便执行特定的业务逻辑,例如记录日志、初始化或清理资源。

一种常见的误解是,可以通过CDI的便携式扩展(Portable Extension)机制,例如监听ProcessAnnotatedType事件,来动态地为javax.enterprise.context.Conversation类添加拦截器绑定。然而,这种方法通常不可行,原因在于Conversation类本身是CDI规范定义的核心组件,其生命周期和行为由容器内部管理,并非典型的用户定义Bean,不适合通过ProcessAnnotatedType事件进行此类拦截器绑定的动态修改。尝试在此事件中访问并修改Conversation类通常会失败,因为它不以普通Bean的方式被处理。

利用CDI上下文生命周期事件进行拦截

CDI提供了一套强大的事件机制,允许开发者监听各种上下文的生命周期事件。对于会话作用域(ConversationScoped),CDI定义了特定的事件来表示其初始化和销毁。通过观察这些事件,我们可以优雅且符合CDI规范地实现对会话生命周期的拦截。

核心思想是创建一个普通的CDI Bean,其中包含带有@Observes注解的方法,并结合@Initialized或@Destroyed限定符以及目标作用域ConversationScoped.class。

会话开始事件

当一个ConversationScoped上下文被初始化时,CDI容器会触发一个@Initialized(ConversationScoped.class)事件。通常,对于基于Servlet的Web应用,此事件的载荷(payload)是javax.servlet.ServletRequest对象。

会话结束事件

类似地,当一个ConversationScoped上下文被销毁时,CDI容器会触发一个@Destroyed(ConversationScoped.class)事件。其载荷同样是javax.servlet.ServletRequest对象。

示例代码:实现会话生命周期观察者

以下是一个实现CDI会话生命周期拦截的示例类:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Destroyed;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.servlet.ServletRequest;

/**
 * CDI会话生命周期观察者,用于拦截会话的开始和结束事件。
 * 此类本身应作为一个CDI Bean被容器发现和管理。
 */
@ApplicationScoped // 或者其他适合的CDI作用域,确保其能被容器发现
public class ConversationLifecycleObserver {

    /**
     * 监听会话开始事件。
     * 当一个ConversationScoped上下文被初始化时触发此方法。
     *
     * @param request 关联的ServletRequest对象,作为事件载荷。
     *                通过此对象可以获取请求相关信息。
     */
    public void onConversationStart(@Observes @Initialized(ConversationScoped.class) ServletRequest request) {
        String sessionId = request.getSession(false) != null ? request.getSession(false).getId() : "N/A";
        System.out.println("------------------------------------------------------------------");
        System.out.println("CDI Conversation Started.");
        System.out.println("  Request URI: " + request.getRequestURI());
        System.out.println("  Session ID: " + sessionId);
        System.out.println("  Timestamp: " + System.currentTimeMillis());
        System.out.println("------------------------------------------------------------------");
        // 在此处添加会话开始时的业务逻辑,例如:
        // - 记录审计日志
        // - 初始化会话相关的统计数据
        // - 设置会话默认值等
    }

    /**
     * 监听会话结束事件。
     * 当一个ConversationScoped上下文被销毁时触发此方法。
     *
     * @param request 关联的ServletRequest对象,作为事件载荷。
     *                通过此对象可以获取请求相关信息。
     */
    public void onConversationEnd(@Observes @Destroyed(ConversationScoped.class) ServletRequest request) {
        String sessionId = request.getSession(false) != null ? request.getSession(false).getId() : "N/A";
        System.out.println("------------------------------------------------------------------");
        System.out.println("CDI Conversation Ended.");
        System.out.println("  Request URI: " + request.getRequestURI());
        System.out.println("  Session ID: " + sessionId);
        System.out.println("  Timestamp: " + System.currentTimeMillis());
        System.out.println("------------------------------------------------------------------");
        // 在此处添加会话结束时的业务逻辑,例如:
        // - 清理会话相关的临时资源
        // - 记录会话的最终状态或统计数据
        // - 触发其他后续处理
    }
}

注意事项与最佳实践

  1. Observer Bean的作用域: ConversationLifecycleObserver类本身需要是一个CDI Bean,因此需要被CDI容器发现。通常,将其标记为@ApplicationScoped或@Singleton(如果使用Jakarta EE 9+)是合适的选择,因为会话生命周期的监听通常是应用级别的。
  2. 事件载荷: 在Web环境中,ServletRequest是ConversationScoped上下文生命周期事件的常见载荷。如果您的应用运行在非Web环境或使用其他上下文实现,事件载荷可能会有所不同,但基本模式(@Observes @Initialized/@Destroyed(Scope.class) PayloadType)保持不变。
  3. 异常处理: 在观察者方法中执行的业务逻辑应妥善处理异常,避免影响CDI容器的正常运行。
  4. 避免直接操作Conversation实例: 尽管您可以在观察者方法中通过CDI.current().select(Conversation.class).get()获取当前的Conversation实例,但通常不建议在这些生命周期事件中调用conversation.begin()或conversation.end(),因为这些事件本身就代表了会话状态的转换。过度干预可能导致不可预测的行为。
  5. 替代方案的局限性: 再次强调,尝试通过ProcessAnnotatedType等便携式扩展机制直接修改或拦截Conversation类本身的方法(如begin()或end())是复杂且通常不推荐的。CDI的事件模型是处理这类需求的标准和推荐方式。

总结

通过利用CDI的上下文生命周期事件,开发者可以以一种健壮且符合规范的方式拦截和响应会话(Conversation)的开始与结束。这种方法不仅避免了直接修改CDI核心组件的复杂性,还提供了清晰的扩展点,使得在会话生命周期的关键时刻集成自定义业务逻辑变得简单而高效。理解并正确运用CDI的事件模型,是构建可维护和可扩展的CDI应用的关键。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

讯飞智文

一款面向学习和办公场景的AI文档创作工具,可辅助生成PPT与Word文档,提高资料整理和内容制作效率。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

相关专题

更多
servlet生命周期
servlet生命周期

Servlet生命周期是指Servlet从创建到销毁的整个过程。本专题为大家提供servlet生命周期的各类文章,大家可以免费体验。

1431

2023.08.08

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

4516

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

326

2025.12.06

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3983

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

974

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

6806

2024.03.12

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

5550

2024.08.16

Go 语言 HTTP 编程与中间件开发教程合集
Go 语言 HTTP 编程与中间件开发教程合集

全面讲解 Go 语言 HTTP 编程的核心知识,涵盖 net/http 标准库的 Server/Handler/HandlerFunc 体系、DefaultServeMux 路由注册与自定义路由器、Request / ResponseWriter 请求响应处理、中间件(Middleware)链式设计模式与常见中间件(日志/CORS/认证/限流)开发、http.Client 的超时配置与连接池管理、Cookie / Session 处理、

581

2026.05.08

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

40

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn