第12讲、Odoo 18 权限控制机制详解

article/2025/6/20 21:02:30

目录

  1. 引言
  2. 权限机制概述
  3. 权限组(Groups)
  4. 访问控制列表(ACL)
  5. 记录规则(Record Rules)
  6. 字段级权限控制
  7. 按钮级权限控制
  8. 菜单级权限控制
  9. 综合案例:多层级权限控制
  10. 最佳实践与注意事项
  11. 总结

引言

Odoo 18 提供了一套完整而灵活的权限控制机制,可以精确控制用户对系统各个层面的访问权限。本文将深入介绍 Odoo 18 的权限控制机制,从权限组到记录规则,从字段级别到按钮级别,再到菜单级别,全面解析其工作原理,并附上实际案例说明。

权限机制概述

Odoo 的权限控制体系是多层次的,从粗到细可以分为以下几个层级:

  1. 菜单级权限:控制用户是否可以看到特定菜单
  2. 模型级权限(ACL):控制用户对整个模型的读、写、创建、删除权限
  3. 记录级权限(Record Rules):控制用户可以访问模型中的哪些记录
  4. 字段级权限:控制用户可以查看或编辑模型中的哪些字段
  5. 按钮级权限:控制用户可以使用界面上的哪些功能按钮

这些权限控制机制相互配合,形成了一个完整的权限管理体系。下面我们将逐一深入介绍每个层级的权限控制机制。

权限组(Groups)

权限组是 Odoo 权限控制的基础,所有权限都是通过权限组来分配的。用户被分配到不同的权限组,从而获得相应的权限。

工作原理

  1. 每个权限组都是 res.groups 模型的一条记录
  2. 用户可以同时属于多个权限组,权限是累加的
  3. 权限组可以继承其他权限组的权限
  4. 权限组可以按类别进行分组

实现方式

权限组通常在模块的 XML 文件中定义:

<record id="group_project_manager" model="res.groups"><field name="name">项目经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_user'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>

字段说明

  • name: 权限组名称
  • category_id: 权限组所属类别
  • implied_ids: 该权限组隐含的其他权限组(继承关系)
  • users: 默认分配到该权限组的用户

案例:项目管理模块的权限组设计

<!-- 项目用户组 -->
<record id="group_project_user" model="res.groups"><field name="name">项目用户</field><field name="category_id" ref="base.module_category_project_management"/>
</record><!-- 项目经理组 -->
<record id="group_project_manager" model="res.groups"><field name="name">项目经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_user'))]"/>
</record><!-- 项目总监组 -->
<record id="group_project_director" model="res.groups"><field name="name">项目总监</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_project_manager'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>

在这个案例中,我们定义了三个权限组:项目用户、项目经理和项目总监。项目经理继承了项目用户的权限,项目总监继承了项目经理的权限,形成了一个权限层级结构。

访问控制列表(ACL)

访问控制列表(ACL)是模型级别的权限控制,用于控制用户对整个模型的读、写、创建、删除权限。

工作原理

  1. ACL 定义了特定权限组对特定模型的权限
  2. 每个 ACL 规则都是 ir.model.access 模型的一条记录
  3. 权限是累加的,如果用户属于多个权限组,则拥有这些权限组的所有权限
  4. 如果没有明确授予权限,则默认没有权限

实现方式

ACL 通常在模块的 security/ir.model.access.csv 文件中定义:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_task_user,project.task.user,model_project_task,group_project_user,1,0,0,0
access_project_task_manager,project.task.manager,model_project_task,group_project_manager,1,1,1,1

字段说明

  • id: ACL 规则的唯一标识符
  • name: ACL 规则的名称
  • model_id:id: 目标模型的外部 ID
  • group_id:id: 权限组的外部 ID
  • perm_read: 是否有读取权限(0 或 1)
  • perm_write: 是否有修改权限(0 或 1)
  • perm_create: 是否有创建权限(0 或 1)
  • perm_unlink: 是否有删除权限(0 或 1)

案例:项目任务的 ACL 设计

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_task_user,project.task.user,model_project_task,group_project_user,1,1,1,0
access_project_task_manager,project.task.manager,model_project_task,group_project_manager,1,1,1,1
access_project_milestone_user,project.milestone.user,model_project_milestone,group_project_user,1,0,0,0
access_project_milestone_manager,project.milestone.manager,model_project_milestone,group_project_manager,1,1,1,1

在这个案例中,项目用户可以读取、修改和创建任务,但不能删除任务;项目经理可以读取、修改、创建和删除任务。对于里程碑,项目用户只能查看,而项目经理可以完全控制。

记录规则(Record Rules)

记录规则是记录级别的权限控制,用于控制用户可以访问模型中的哪些记录。

工作原理

  1. 记录规则定义了特定权限组可以访问模型中的哪些记录
  2. 每个记录规则都是 ir.rule 模型的一条记录
  3. 记录规则使用域表达式(domain)来过滤记录
  4. 如果用户属于多个权限组,则可以访问满足任一记录规则的记录
  5. 记录规则可以针对读取、修改、创建和删除操作分别设置

实现方式

记录规则通常在模块的 XML 文件中定义:

<record id="project_task_rule_user" model="ir.rule"><field name="name">项目任务:用户只能看到自己的任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_user'))]"/><field name="perm_read" eval="1"/><field name="perm_write" eval="1"/><field name="perm_create" eval="1"/><field name="perm_unlink" eval="0"/>
</record>

字段说明

  • name: 记录规则的名称
  • model_id: 目标模型的引用
  • domain_force: 域表达式,用于过滤记录
  • groups: 适用的权限组
  • perm_read: 是否适用于读取操作
  • perm_write: 是否适用于修改操作
  • perm_create: 是否适用于创建操作
  • perm_unlink: 是否适用于删除操作

案例:项目任务的记录规则设计

<!-- 项目用户只能看到自己负责的任务 -->
<record id="project_task_rule_user" model="ir.rule"><field name="name">项目任务:用户只能看到自己的任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_user'))]"/>
</record><!-- 项目经理可以看到自己项目中的所有任务 -->
<record id="project_task_rule_manager" model="ir.rule"><field name="name">项目任务:经理可以看到自己项目中的所有任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[('project_id.user_id', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_project_manager'))]"/>
</record><!-- 项目总监可以看到所有任务 -->
<record id="project_task_rule_director" model="ir.rule"><field name="name">项目任务:总监可以看到所有任务</field><field name="model_id" ref="model_project_task"/><field name="domain_force">[(1, '=', 1)]</field><field name="groups" eval="[(4, ref('group_project_director'))]"/>
</record>

在这个案例中,项目用户只能看到分配给自己的任务,项目经理可以看到自己负责的项目中的所有任务,而项目总监可以看到所有任务。

字段级权限控制

字段级权限控制用于控制用户可以查看或编辑模型中的哪些字段。

工作原理

  1. 字段级权限通过字段的 groups 属性来控制
  2. 只有属于指定权限组的用户才能查看或编辑该字段
  3. 字段级权限可以在模型定义中设置,也可以在视图中设置

实现方式

在模型定义中设置字段级权限
class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'name = fields.Char('任务名称', required=True)description = fields.Text('任务描述')priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')budget = fields.Float('预算', groups='project.group_project_manager')actual_cost = fields.Float('实际成本', groups='project.group_project_director')
在视图中设置字段级权限
<field name="budget" groups="project.group_project_manager"/>
<field name="actual_cost" groups="project.group_project_director"/>

案例:项目任务的字段级权限设计

class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'name = fields.Char('任务名称', required=True)description = fields.Text('任务描述')user_id = fields.Many2one('res.users', string='负责人')date_deadline = fields.Date('截止日期')priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')# 只有项目经理及以上权限才能看到预算字段budget = fields.Float('预算', groups='project.group_project_manager')# 只有项目总监才能看到实际成本字段actual_cost = fields.Float('实际成本', groups='project.group_project_director')# 只有项目总监才能看到利润率字段profit_margin = fields.Float('利润率 (%)', compute='_compute_profit_margin', groups='project.group_project_director')@api.depends('budget', 'actual_cost')def _compute_profit_margin(self):for task in self:if task.budget and task.actual_cost:task.profit_margin = (task.budget - task.actual_cost) / task.budget * 100else:task.profit_margin = 0.0

在视图中的应用:

<record id="view_task_form" model="ir.ui.view"><field name="name">project.task.form</field><field name="model">project.task</field><field name="arch" type="xml"><form><sheet><group><field name="name"/><field name="user_id"/><field name="date_deadline"/><field name="priority"/><!-- 只有项目经理及以上权限才能看到预算字段 --><field name="budget" groups="project.group_project_manager"/><!-- 只有项目总监才能看到实际成本和利润率字段 --><field name="actual_cost" groups="project.group_project_director"/><field name="profit_margin" groups="project.group_project_director"/></group><field name="description"/></sheet></form></field>
</record>

在这个案例中,预算字段只对项目经理及以上权限可见,而实际成本和利润率字段只对项目总监可见。

按钮级权限控制

按钮级权限控制用于控制用户可以使用界面上的哪些功能按钮。

工作原理

  1. 按钮级权限通过按钮的 groups 属性来控制
  2. 只有属于指定权限组的用户才能看到和使用该按钮
  3. 按钮级权限在视图中设置

实现方式

<button name="action_approve" string="批准" type="object" groups="project.group_project_manager"/>

案例:项目任务的按钮级权限设计

<record id="view_task_form" model="ir.ui.view"><field name="name">project.task.form</field><field name="model">project.task</field><field name="arch" type="xml"><form><header><field name="state" widget="statusbar"/><!-- 任何用户都可以提交任务 --><button name="action_submit" string="提交" type="object" attrs="{'invisible': [('state', '!=', 'draft')]}"/><!-- 只有项目经理才能批准任务 --><button name="action_approve" string="批准" type="object" groups="project.group_project_manager"attrs="{'invisible': [('state', '!=', 'submitted')]}"/><!-- 只有项目总监才能关闭任务 --><button name="action_close" string="关闭" type="object" groups="project.group_project_director"attrs="{'invisible': [('state', '!=', 'approved')]}"/><!-- 任何用户都可以取消任务,但需要确认 --><button name="action_cancel" string="取消" type="object" confirm="确定要取消这个任务吗?"attrs="{'invisible': [('state', 'in', ['cancelled', 'done'])]}"/></header><sheet><!-- 表单内容 --></sheet></form></field>
</record>

对应的 Python 方法:

class ProjectTask(models.Model):_name = 'project.task'_description = '项目任务'state = fields.Selection([('draft', '草稿'),('submitted', '已提交'),('approved', '已批准'),('done', '已完成'),('cancelled', '已取消'),], string='状态', default='draft', tracking=True)def action_submit(self):self.write({'state': 'submitted'})def action_approve(self):self.write({'state': 'approved'})def action_close(self):self.write({'state': 'done'})def action_cancel(self):self.write({'state': 'cancelled'})

在这个案例中,任何用户都可以提交和取消任务,但只有项目经理才能批准任务,只有项目总监才能关闭任务。

菜单级权限控制

菜单级权限控制用于控制用户可以看到哪些菜单项。

工作原理

  1. 菜单级权限通过菜单的 groups 属性来控制
  2. 只有属于指定权限组的用户才能看到该菜单
  3. 菜单级权限在菜单定义中设置

实现方式

<menuitem id="menu_project_task" name="任务" parent="menu_project" action="action_project_task" groups="group_project_user"/>

案例:项目管理模块的菜单级权限设计

<!-- 主菜单:所有项目用户可见 -->
<menuitem id="menu_project_root" name="项目" sequence="40" groups="group_project_user"/><!-- 项目菜单:所有项目用户可见 -->
<menuitem id="menu_project" name="项目" parent="menu_project_root" sequence="10"/>
<menuitem id="menu_project_list" name="项目列表" parent="menu_project" action="action_project_list" sequence="10"/>
<menuitem id="menu_project_task" name="任务" parent="menu_project" action="action_project_task" sequence="20"/><!-- 报告菜单:只有项目经理可见 -->
<menuitem id="menu_project_report" name="报告" parent="menu_project_root" sequence="20" groups="group_project_manager"/>
<menuitem id="menu_project_task_analysis" name="任务分析" parent="menu_project_report" action="action_project_task_analysis" sequence="10"/><!-- 配置菜单:只有项目总监可见 -->
<menuitem id="menu_project_config" name="配置" parent="menu_project_root" sequence="30" groups="group_project_director"/>
<menuitem id="menu_project_tags" name="标签" parent="menu_project_config" action="action_project_tags" sequence="10"/>
<menuitem id="menu_project_stages" name="阶段" parent="menu_project_config" action="action_project_stages" sequence="20"/>

在这个案例中,所有项目用户都可以看到项目和任务菜单,但只有项目经理才能看到报告菜单,只有项目总监才能看到配置菜单。

综合案例:多层级权限控制

下面我们通过一个完整的项目需求管理系统案例,展示如何综合运用各种权限控制机制。

业务场景

我们要开发一个项目需求管理系统,包含模型 project.requirement,需求如下:

用户角色权限需求
普通员工(Employee)只能查看和创建需求,只能看到自己创建的需求记录,不能看到预算和成本信息
部门经理(Manager)可以查看、创建、修改需求,可以看到本部门所有员工的需求,可以看到预算信息但不能看到成本信息,可以批准需求
高级管理层(Director)拥有所有权限,可以看到所有需求,可以看到预算和成本信息,可以批准和关闭需求

实现步骤

1. 定义权限组
<!-- 需求用户组 -->
<record id="group_requirement_user" model="res.groups"><field name="name">需求用户</field><field name="category_id" ref="base.module_category_project_management"/>
</record><!-- 需求经理组 -->
<record id="group_requirement_manager" model="res.groups"><field name="name">需求经理</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_requirement_user'))]"/>
</record><!-- 需求总监组 -->
<record id="group_requirement_director" model="res.groups"><field name="name">需求总监</field><field name="category_id" ref="base.module_category_project_management"/><field name="implied_ids" eval="[(4, ref('group_requirement_manager'))]"/><field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
2. 定义访问控制列表(ACL)
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_requirement_user,project.requirement.user,model_project_requirement,group_requirement_user,1,0,1,0
access_project_requirement_manager,project.requirement.manager,model_project_requirement,group_requirement_manager,1,1,1,0
access_project_requirement_director,project.requirement.director,model_project_requirement,group_requirement_director,1,1,1,1
3. 定义记录规则
<!-- 普通用户只能看到自己创建的需求 -->
<record id="rule_requirement_user_own" model="ir.rule"><field name="name">需求用户只能看到自己的需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[('create_uid', '=', user.id)]</field><field name="groups" eval="[(4, ref('group_requirement_user'))]"/>
</record><!-- 经理可以看到本部门所有需求 -->
<record id="rule_requirement_manager_department" model="ir.rule"><field name="name">需求经理可以看到本部门的需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[('department_id', '=', user.employee_id.department_id.id)]</field><field name="groups" eval="[(4, ref('group_requirement_manager'))]"/>
</record><!-- 总监可以看到所有需求 -->
<record id="rule_requirement_director_all" model="ir.rule"><field name="name">需求总监可以看到所有需求</field><field name="model_id" ref="model_project_requirement"/><field name="domain_force">[(1, '=', 1)]</field><field name="groups" eval="[(4, ref('group_requirement_director'))]"/>
</record>
4. 定义模型和字段级权限
class ProjectRequirement(models.Model):_name = 'project.requirement'_description = '项目需求'name = fields.Char('需求名称', required=True)description = fields.Text('需求描述')department_id = fields.Many2one('hr.department', string='所属部门', default=lambda self: self.env.user.employee_id.department_id)priority = fields.Selection([('0', '低'),('1', '中'),('2', '高'),], string='优先级', default='1')state = fields.Selection([('draft', '草稿'),('submitted', '已提交'),('approved', '已批准'),('done', '已完成'),('cancelled', '已取消'),], string='状态', default='draft', tracking=True)# 只有经理及以上权限才能看到预算字段budget = fields.Float('预算', groups='project_requirement.group_requirement_manager')# 只有总监才能看到成本字段cost = fields.Float('成本', groups='project_requirement.group_requirement_director')# 只有总监才能看到利润率字段profit_margin = fields.Float('利润率 (%)', compute='_compute_profit_margin', groups='project_requirement.group_requirement_director')@api.depends('budget', 'cost')def _compute_profit_margin(self):for req in self:if req.budget and req.cost:req.profit_margin = (req.budget - req.cost) / req.budget * 100else:req.profit_margin = 0.0def action_submit(self):self.write({'state': 'submitted'})def action_approve(self):self.write({'state': 'approved'})def action_done(self):self.write({'state': 'done'})def action_cancel(self):self.write({'state': 'cancelled'})
5. 定义视图和按钮级权限
<record id="view_requirement_form" model="ir.ui.view"><field name="name">project.requirement.form</field><field name="model">project.requirement</field><field name="arch" type="xml"><form><header><field name="state" widget="statusbar"/><!-- 任何用户都可以提交需求 --><button name="action_submit" string="提交" type="object" attrs="{'invisible': [('state', '!=', 'draft')]}"/><!-- 只有经理及以上才能批准需求 --><button name="action_approve" string="批准" type="object" groups="project_requirement.group_requirement_manager"attrs="{'invisible': [('state', '!=', 'submitted')]}"/><!-- 只有总监才能完成需求 --><button name="action_done" string="完成" type="object" groups="project_requirement.group_requirement_director"attrs="{'invisible': [('state', '!=', 'approved')]}"/><!-- 任何用户都可以取消需求 --><button name="action_cancel" string="取消" type="object" confirm="确定要取消这个需求吗?"attrs="{'invisible': [('state', 'in', ['cancelled', 'done'])]}"/></header><sheet><group><field name="name"/><field name="department_id"/><field name="priority"/><!-- 只有经理及以上才能看到预算 --><field name="budget" groups="project_requirement.group_requirement_manager"/><!-- 只有总监才能看到成本和利润率 --><field name="cost" groups="project_requirement.group_requirement_director"/><field name="profit_margin" groups="project_requirement.group_requirement_director"/></group><field name="description"/></sheet></form></field>
</record>
6. 定义菜单级权限
<!-- 主菜单:所有需求用户可见 -->
<menuitem id="menu_requirement_root" name="需求管理" sequence="50" groups="project_requirement.group_requirement_user"/><!-- 需求菜单:所有需求用户可见 -->
<menuitem id="menu_requirement" name="需求" parent="menu_requirement_root" sequence="10"/>
<menuitem id="menu_requirement_list" name="需求列表" parent="menu_requirement" action="action_requirement_list" sequence="10"/><!-- 报告菜单:只有经理及以上可见 -->
<menuitem id="menu_requirement_report" name="报告" parent="menu_requirement_root" sequence="20" groups="project_requirement.group_requirement_manager"/>
<menuitem id="menu_requirement_analysis" name="需求分析" parent="menu_requirement_report" action="action_requirement_analysis" sequence="10"/><!-- 配置菜单:只有总监可见 -->
<menuitem id="menu_requirement_config" name="配置" parent="menu_requirement_root" sequence="30" groups="project_requirement.group_requirement_director"/>
<menuitem id="menu_requirement_tags" name="标签" parent="menu_requirement_config" action="action_requirement_tags" sequence="10"/>

权限效果

  1. 普通员工

    • 可以看到需求管理菜单和需求列表菜单
    • 可以查看和创建需求,但不能修改和删除
    • 只能看到自己创建的需求
    • 看不到预算、成本和利润率字段
    • 可以提交和取消需求,但不能批准和完成需求
  2. 部门经理

    • 可以看到需求管理菜单、需求列表菜单和报告菜单
    • 可以查看、创建和修改需求,但不能删除
    • 可以看到本部门所有员工的需求
    • 可以看到预算字段,但看不到成本和利润率字段
    • 可以提交、批准和取消需求,但不能完成需求
  3. 高级管理层

    • 可以看到所有菜单
    • 可以查看、创建、修改和删除需求
    • 可以看到所有需求
    • 可以看到预算、成本和利润率字段
    • 可以执行所有操作(提交、批准、完成和取消需求)

最佳实践与注意事项

  1. 权限设计原则

    • 遵循最小权限原则,只给用户必要的权限
    • 使用权限组继承关系简化权限管理
    • 权限控制应该从粗到细,先控制菜单和模型级权限,再控制记录级和字段级权限
  2. 性能考虑

    • 记录规则会影响查询性能,特别是复杂的域表达式
    • 避免使用过于复杂的记录规则
    • 考虑使用索引优化记录规则的性能
  3. 安全注意事项

    • 菜单级权限只是隐藏菜单,不是真正的安全控制
    • 必须结合 ACL 和记录规则来实现完整的权限控制
    • 不要依赖客户端的权限控制,服务器端必须进行权限验证
  4. 调试技巧

    • 使用开发者模式查看权限问题
    • 检查用户所属的权限组
    • 检查模型的 ACL 规则
    • 检查记录规则的域表达式

总结

Odoo 18 提供了一套完整而灵活的权限控制机制,可以从多个层面精确控制用户的权限:

  1. 权限组(Groups):权限控制的基础,用户通过所属的权限组获得相应的权限
  2. 访问控制列表(ACL):模型级别的权限控制,控制用户对整个模型的读、写、创建、删除权限
  3. 记录规则(Record Rules):记录级别的权限控制,控制用户可以访问模型中的哪些记录
  4. 字段级权限:控制用户可以查看或编辑模型中的哪些字段
  5. 按钮级权限:控制用户可以使用界面上的哪些功能按钮
  6. 菜单级权限:控制用户可以看到哪些菜单项

这些权限控制机制相互配合,形成了一个完整的权限管理体系,可以满足各种复杂的业务需求。通过合理设计和配置这些权限控制机制,可以确保系统的安全性和可用性,同时提供良好的用户体验。


http://www.hkcw.cn/article/midvTAgfqT.shtml

相关文章

AIGC学习笔记(8)——AI大模型开发工程师

文章目录 AI大模型开发工程师007 LangChain之Model IO模块1 Model IO核心概念2 Model IO代码实战什么是LCEL&#xff1f;ModelModel的分类LLMsChatModel PromptPrompt templatesExample selectorsOutput parsers AI大模型开发工程师 007 LangChain之Model IO模块 1 Model IO核…

Java 文件操作 和 IO(5)-- 综合案例练习 -- 示例一

题目描述&#xff1a;扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否要删除该文件 文章目录 题目描述&#xff1a;扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&…

Leetcode 465. 最优账单平衡

1.题目基本信息 1.1.题目描述 给你一个表示交易的数组 transactions &#xff0c;其中 transactions[i] [fromi, toi, amounti] 表示 ID fromi 的人给 ID toi 的人共计 amounti $ 。 请你计算并返回还清所有债务的最小交易笔数。 1.2.题目地址 https://leetcode.cn/pro…

【沉浸式求职学习day51】【发送邮件】【javaweb结尾】

沉浸式求职学习 邮件发送原理及实现1.概述2.简单邮件3.复杂邮件 网站注册发送邮件功能实现 邮件发送原理及实现 1.概述 传输协议 SMTP协议 发送邮件&#xff1a; 我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。POP3协议 接收邮件&#…

标题:2025海外短剧爆发年:APP+H5双端系统开发,解锁全球流量与变现新大陆

描述&#xff1a; 2025年出海新风口&#xff01;深度解析海外短剧系统开发核心&#xff08;APPH5双端&#xff09;&#xff0c;揭秘高效开发策略与商业化路径&#xff0c;助您抢占万亿美元市场&#xff01; 全球娱乐消费模式正在剧变。2025年&#xff0c;海外短剧市场已从蓝海…

uni-app学习笔记十六-vue3页面生命周期(三)

uni-app官方文档页面生命周期部分位于页面 | uni-app官网。 本篇再介绍2个生命周期 1.onUnload&#xff1a;用于监听页面卸载。 当页面被关闭时&#xff0c;即页面的缓存被清掉时触发加载onUnload函数。 例如:在demo6页面点击跳转到demo4&#xff0c;在demo4页面回退不了到d…

钉钉红包性能优化之路

一、业务背景 请客红包、小礼物作为饿了么自研的业务产品&#xff0c;在钉钉的一方化入口中常驻&#xff0c;作为高UV、PV的toB产品&#xff0c;面对不同设备环境的用户&#xff0c;经常会偶尔得到一些用户反馈&#xff0c;如【页面白屏太久了】、【卡住了】等等&#xff0c;本…

鲲鹏Arm+麒麟V10 K8s 离线部署教程

针对鲲鹏 CPU 麒麟 V10 的离线环境&#xff0c;手把手教你从环境准备到应用上线&#xff0c;所有依赖包提前打包好&#xff0c;步骤写成傻瓜式操作指南。 一、环境规划# 准备至少两台机器。 架构OS作用Arm64任意&#xff0c;Mac 也可以下载离线包Arm64麒麟 V10单机部署 K8s…

Redis主从复制详解

概述 Redis 的主从复制&#xff08;Master-Slave Replication&#xff09;是实现数据备份、读写分离和水平扩展的核心机制之一。通过主从复制&#xff0c;一个主节点&#xff08;Master&#xff09;可以将数据同步到多个从节点&#xff08;Slave&#xff09;&#xff0c;从节点…

16.进程间通信(二)

一、命名管道 1.概念 匿名管道解决了具有血缘关系的进程之间的通信&#xff0c;如果两个进程毫不相干&#xff0c;如何进行通信呢&#xff1f;通过文件&#xff0c;管道文件。 对于两个不同进程&#xff0c;打开同一路径下的同一文件&#xff0c;inode和文件内核缓冲区不会加载…

优化的两极:凸优化与非凸优化的理论、应用与挑战

在机器学习、工程设计、经济决策等众多领域&#xff0c;优化问题无处不在。而在优化理论的世界里&#xff0c;凸优化与非凸优化如同两个截然不同的 “王国”&#xff0c;各自有着独特的规则、挑战和应用场景。今天&#xff0c;就让我们深入探索这两个优化领域的核心差异、算法特…

day15 leetcode-hot100-29(链表8)

19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 1.暴力法 思路 &#xff08;1&#xff09;先获取链表的长度L &#xff08;2&#xff09;然后再次遍历链表到L-n的位置&#xff0c;直接让该指针的节点指向下下一个即可。 2.哈希表 思路 &#xff0…

rtpinsertsound:语音注入攻击!全参数详细教程!Kali Linux教程!

简介 2006年8月至9月期间&#xff0c;我们创建了一个用于将音频插入指定音频&#xff08;即RTP&#xff09;流的工具。该工具名为rtpinsertsound。 该工具已在Linux Red Hat Fedora Core 4平台&#xff08;奔腾IV&#xff0c;2.5 GHz&#xff09;上进行了测试&#xff0c;但预…

谷歌Stitch:AI赋能UI设计,免费高效新利器

在AI技术日新月异的今天&#xff0c;各大科技巨头都在不断刷新我们对智能工具的认知。最近&#xff0c;谷歌在其年度I/O开发者大会期间&#xff0c;除了那些聚光灯下的重磅发布&#xff0c;还悄然上线了一款令人惊喜的AI工具——Stitch。这是一款全新的、完全免费的AI驱动UI&am…

PowerBI企业运营分析——线性回归销售预测

PowerBI企业运营分析——线性回归销售预测 欢迎来到Powerbi小课堂&#xff0c;在竞争激烈的市场环境中&#xff0c;企业运营分析平台成为提升竞争力的核心工具。 该平台通过整合多源数据&#xff0c;实现关键指标的实时监控&#xff0c;从而迅速洞察业务动态&#xff0c;精准…

<4>, Qt窗口

目录 一&#xff0c;菜单栏 二&#xff0c;工具栏 三&#xff0c;状态栏 四&#xff0c;浮动窗口 五&#xff0c;对话框 一&#xff0c;菜单栏 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);// 创建菜单栏…

多目标粒子群优化算法(MOPSO),用于解决无人机三维路径规划问题,Matlab代码实现

多目标粒子群优化算法&#xff08;MOPSO&#xff09;&#xff0c;用于解决无人机三维路径规划问题&#xff0c;Matlab代码实现 目录 多目标粒子群优化算法&#xff08;MOPSO&#xff09;&#xff0c;用于解决无人机三维路径规划问题&#xff0c;Matlab代码实现效果一览基本介绍…

具有离散序列建模的统一多模态大语言模型【AnyGPT】

第1章 Instruction 在人工智能领域、多模态只语言模型的发展正迎来新的篇章。传统的大型语言模型(LLM)在理解和生成人类语言方面展现出了卓越的能力&#xff0c;但这些能力通常局限于 文本处理。然而&#xff0c;现实世界是一个本质上多模态的环境&#xff0c;生物体通过视觉、…

嵌入式学习笔记 - STM32 HAL库以及标准库内核以及外设头文件区别问题

一 CMSIS内核驱动文件夹 标准库中CMSIS内核驱动文件夹中&#xff0c;仅包含两个.h文件&#xff0c;其中stm32f10x.h 为stm10系列底层文件如总线以及各片上外设模块寄存器地址&#xff0c;system_stm32f10x.h为系统底层配置文件&#xff0c;主要为时钟配置。 HAL库中CMSIS内核驱…

LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表

LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表 第 一 题 - - - 移 除 链 表 元 素方 法 一 - - - 原 地 删 除方 法 二 - - - 双 指 针方 法 三 - - - 尾 插 第 二 题 - - - 反 转 链 表方 法 一 - - - 迭 代方 法 二 - - - 采 用 头 插 创 建 新 链 表 总 结 &a…