服务中从零实现应用服务的领域实体及消息处理
【摘要】 1 简介JAVAEE中有3个类型的Bean,本文例子中的组件实现了EJB中Bean的这三种类型功能: Session Bean, Entity Bean, Message-Driven Bean.比如Session Bean的职责:维护一个短暂会话,当客户端执行完成后,Session Bean和它的数据会消失。Entitv Bean的职责:维护一行持久稳固的数据...
1 简介
JAVAEE中有3个类型的Bean,本文例子中的组件实现了EJB中Bean的这三种类型功能:
Session Bean,
Entity Bean,
Message-Driven Bean.
比如Session Bean的职责:维护一个短暂会话,当客户端执行完成后,Session Bean和它的数据会消失。
Entitv Bean的职责:维护一行持久稳固的数据,如果客户端终止或者服务结束,底层的服务会负责entity Bean数据的存储。
Message-Driven Bean的职责:结合了Session Bean 和JMS,允许异步接收消息。
2 实现Bean的功能替代
在web框架的费用管理系统中,可以通过不同组件和职责实现 EJB 的三种 Bean(Session Bean、Entity Bean、Message-Driven Bean)的功能。以下是对 EJB 三种类型在示例中对应实现的映射和说明:
2.1. Session Bean 对应
职责:
维护短暂会话。
生命周期与客户端请求相关,完成后即销毁。
对应的组件:
在费用管理系统中,Session Bean 的职责可以由应用层服务 (ExpenseAppService) 来模拟。它的逻辑在每次请求时
被实例化,用于处理请求相关的业务逻辑,并在请求结束后销毁,不保存持久状态。
示例:
type ExpenseAppService struct {
expenseRepo domain.ExpenseRepository
}
func NewExpenseAppService(repo domain.ExpenseRepository) *ExpenseAppService {
return &ExpenseAppService{expenseRepo: repo}
}
func (s *ExpenseAppService) CreateExpense(req CreateExpenseRequest) error {
expense := domain.NewExpense(req.UserID, req.Amount, req.Category, req.Remark)
return s.expenseRepo.Save(expense)
}
作用:每个 HTTP 请求都会创建一个 ExpenseAppService 实例,用于处理当前的会话任务,完成后释放。
短暂性:ExpenseAppService 的实例仅在请求期间有效。
2.2. Entity Bean 对应
职责:
负责与数据库中的持久数据交互。
实现数据的创建、读取、更新和删除(CRUD)。
生命周期独立于客户端请求。
对应的组件:
在费用管理系统中,Entity Bean 的职责可以由领域层的实体类 (Expense) 和基础设施层的存储库 (InMemoryExpenseRepository) 来实现。
示例:
实体类(Entity Bean 功能核心):
type Expense struct {
ID string
UserID string
Amount float64
Category string
Remark string
CreatedAt time.Time
}
func NewExpense(userID string, amount float64, category, remark string) *Expense {
return &Expense{
ID: generateID(), // 自定义 ID 生成逻辑
UserID: userID,
Amount: amount,
Category: category,
Remark: remark,
CreatedAt: time.Now(),
}
}
基础设施层的存储库(Entity Bean 的持久化支持):
type InMemoryExpenseRepository struct {
data map[string][]*domain.Expense
}
func (r *InMemoryExpenseRepository) Save(expense *domain.Expense) error {
r.data[expense.UserID] = append(r.data[expense.UserID], expense)
return nil
}
作用:
Expense 表示持久化对象,维护业务相关数据。
InMemoryExpenseRepository 负责与底层存储(如数据库或内存)交互,确保实体的持久性。
2.3. Message-Driven Bean 对应
职责:
结合会话功能和消息驱动机制。异步接收和处理消息。
对应的组件:
在框架中,Message-Driven Bean 的功能可以通过消息队列系统(如 RabbitMQ、Kafka 等)和消费逻辑来实现。这种组件通常独立于 HTTP 请求生命周期,专注于处理异步任务。
示例:
领域事件处理器(模拟 Message-Driven Bean 的功能):
type ExpenseMessageProcessor struct {
repo domain.ExpenseRepository
}
func NewExpenseMessageProcessor(repo domain.ExpenseRepository) *ExpenseMessageProcessor {
return &ExpenseMessageProcessor{repo: repo}
}
// 模拟异步消费逻辑
func (p *ExpenseMessageProcessor) ProcessMessage(msg string) error {
// 假设消息内容包含 JSON 格式的费用数据
var expenseData domain.Expense
if err := json.Unmarshal([]byte(msg), &expenseData); err != nil {
return err
}
return p.repo.Save(&expenseData)
}
消息驱动的模拟场景: 假设通过 RabbitMQ 消息队列异步传递费用记录,消费者监听并保存数据:
func StartMessageListener(processor *ExpenseMessageProcessor) {
go func() {
for {
// 假设从队列中获取消息
msg := getMessageFromQueue() // 模拟消息队列接口
if err := processor.ProcessMessage(msg); err != nil {
log.Printf("Failed to process message: %v", err)
}
}
}()
}
作用:
ExpenseMessageProcessor 接收和处理异步消息,将其转化为领域模型并保存。
消息队列模拟了异步事件的处理逻辑。
3 小结
对应关系表
EJB Bean 类型 Gin 架构中对应组件 职责与功能
Session Bean 应用层服务(ExpenseAppService) 处理短暂业务逻辑,与客户端请求生命周期一致。
Entity Bean 领域实体类(Expense)和存储库(InMemoryExpenseRepository) 表示和维护持久化数据,与底层存储交互,支持 CRUD。
Message-Driven Bean 消息处理器(ExpenseMessageProcessor) 异步接收消息并处理,将其保存为持久化对象(领域事件处理)。
优势
通过分层解耦,符合 DDD 设计思想,职责清晰。
消息驱动的异步逻辑提高了系统扩展性和性能。
与 EJB 的设计模式类似,适用于现代微服务架构中不同服务的拆分。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)