审核功能的常见场景 管理系统的核心功能之一,常见于以下场景:
- 用户提交的内容(如文章、评论)需要管理员审核后才能公开显示。
- 电商平台中,订单需要经过风控审核或人工确认。
- 企业内部流程审批(如请假申请、报销单)。
实现审核状态的核心在于状态的定义、流转规则的控制以及权限管理,下面通过代码示例详细说明。
审核状态的数据模型设计
数据库字段设计
在数据库表中,通常用status
字段存储审核状态,建议使用ENUM
类型或整型(对应枚举值):
CREATE TABLE article ( id INT PRIMARY KEY AUTO_INCREMENT,VARCHAR(255), content TEXT, status ENUM('DRAFT', 'PENDING_REVIEW', 'APPROVED', 'REJECTED') NOT NULL DEFAULT 'DRAFT', created_by INT, reviewed_by INT, reviewed_at DATETIME );
Java枚举定义
使用枚举清晰表达状态含义,避免“魔法数字”:
public enum AuditStatus { DRAFT, // 草稿 PENDING_REVIEW, // 待审核 APPROVED, // 审核通过 REJECTED // 驳回 }
审核状态流转控制
状态变更规则
需定义允许的状态变更路径,
- 草稿(DRAFT) → 提交审核(PENDING_REVIEW)
- 待审核(PENDING_REVIEW) → 通过(APPROVED)或驳回(REJECTED)
- 驳回(REJECTED) → 重新提交(PENDING_REVIEW)
实现状态机
使用条件判断或状态模式(State Pattern)确保合法性:
public class ArticleService { public void submitForReview(Article article) { if (article.getStatus() != AuditStatus.DRAFT) { throw new IllegalStateException("仅草稿状态可提交审核"); } article.setStatus(AuditStatus.PENDING_REVIEW); } public void approveArticle(Article article, User reviewer) { if (article.getStatus() != AuditStatus.PENDING_REVIEW) { throw new IllegalStateException("当前状态不允许通过审核"); } article.setStatus(AuditStatus.APPROVED); article.setReviewedBy(reviewer.getId()); article.setReviewedAt(LocalDateTime.now()); } }
权限控制
确保只有授权用户(如管理员)可以操作审核:
使用Spring Security注解
@PreAuthorize("hasRole('ADMIN')") public void approveArticle(Long articleId) { // 审核逻辑 }
自定义权限校验
if (!user.hasPermission("ARTICLE:REVIEW")) { throw new AccessDeniedException("无审核权限"); }
日志记录与追踪
记录状态变更的完整轨迹,便于审计:
@Transactional public void updateStatus(Article article, AuditStatus newStatus, User operator) { AuditLog log = new AuditLog(); log.setArticleId(article.getId()); log.setOldStatus(article.getStatus()); log.setNewStatus(newStatus); log.setOperatorId(operator.getId()); log.setOperateTime(LocalDateTime.now()); auditLogRepository.save(log); article.setStatus(newStatus); }
完整代码示例
// 实体类 @Entity public class Article { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String content; @Enumerated(EnumType.STRING) private AuditStatus status; private Long createdBy; private Long reviewedBy; private LocalDateTime reviewedAt; } // Service层核心方法 @Service public class ArticleService { @Autowired private ArticleRepository articleRepository; @Transactional @PreAuthorize("hasPermission(#articleId, 'REVIEW')") public void approveArticle(Long articleId, User reviewer) { Article article = articleRepository.findById(articleId) .orElseThrow(() -> new ResourceNotFoundException("文章不存在")); if (article.getStatus() != AuditStatus.PENDING_REVIEW) { throw new BusinessException("非法状态变更"); } article.setStatus(AuditStatus.APPROVED); article.setReviewedBy(reviewer.getId()); article.setReviewedAt(LocalDateTime.now()); } }
最佳实践
- 并发控制:使用数据库乐观锁(
@Version
)防止状态覆盖。 - 通知机制:审核结果通过邮件/站内信通知提交者。
- 配置化:将状态流转规则存储在数据库或配置文件中,提高灵活性。
- 自动化:结合规则引擎实现部分自动审核(如敏感词检测)。
引用说明
- 状态模式:《设计模式:可复用面向对象软件的基础》
- Spring Security权限控制:https://spring.io/projects/spring-security
- 乐观锁实现:JPA
@Version
注解官方文档
结束)
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/5207.html