java构建一个OA审批系统

构建一个完整的OA审批系统涉及多个模块,包括用户管理、权限控制、审批流程设计以及前端界面等。以下是一个综合性的示例,展示了如何整合这些模块并实现基本功能。

### 数据库设计

首先,定义一些基本的数据库表结构,用于存储用户信息和审批相关数据:

-- 用户表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(100) NOT NULL,
    role ENUM('EMPLOYEE', 'MANAGER', 'ADMIN') NOT NULL
);

-- 审批请求表
CREATE TABLE approval_requests (
    id INT AUTO_INCREMENT PRIMARY KEY,
    applicant_id INT NOT NULL,
    status ENUM('PENDING', 'APPROVED', 'REJECTED') NOT NULL DEFAULT 'PENDING',
    request_text TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    approved_at TIMESTAMP,
    approver_id INT,
    approval_comment TEXT
);

### Java代码实现

#### 实体类定义

定义Java实体类对应数据库表结构:

// User.java
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String username;
    private String password;

    @Enumerated(EnumType.STRING)
    private UserRole role;
    // 省略getter和setter
}

// ApprovalRequest.java
@Entity
@Table(name = "approval_requests")
public class ApprovalRequest {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "applicant_id", nullable = false)
    private User applicant;

    @Enumerated(EnumType.STRING)
    private ApprovalStatus status;

    private String requestText;
    private LocalDateTime createdAt;
    private LocalDateTime approvedAt;

    @ManyToOne
    @JoinColumn(name = "approver_id")
    private User approver;

    private String approvalComment;
    // 省略getter和setter
}

#### 数据访问对象(DAO)

编写DAO接口和实现类,用于数据的持久化操作:

// UserDao.java
public interface UserDao {
    User findByUsername(String username);
    void save(User user);
}

// UserDaoImpl.java
public class UserDaoImpl implements UserDao {
    private EntityManager entityManager;

    public UserDaoImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public User findByUsername(String username) {
        try {
            return entityManager.createQuery("FROM User WHERE username = :username", User.class)
                                .setParameter("username", username)
                                .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Override
    public void save(User user) {
        entityManager.getTransaction().begin();
        entityManager.persist(user);
        entityManager.getTransaction().commit();
    }
}

// ApprovalRequestDao.java
public interface ApprovalRequestDao {
    ApprovalRequest findById(Long id);
    void save(ApprovalRequest request);
    List<ApprovalRequest> findByApplicant(User applicant);
}

// ApprovalRequestDaoImpl.java
public class ApprovalRequestDaoImpl implements ApprovalRequestDao {
    private EntityManager entityManager;

    public ApprovalRequestDaoImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public ApprovalRequest findById(Long id) {
        return entityManager.find(ApprovalRequest.class, id);
    }

    @Override
    public void save(ApprovalRequest request) {
        entityManager.getTransaction().begin();
        entityManager.persist(request);
        entityManager.getTransaction().commit();
    }

    @Override
    public List<ApprovalRequest> findByApplicant(User applicant) {
        return entityManager.createQuery("FROM ApprovalRequest WHERE applicant = :applicant", ApprovalRequest.class)
                            .setParameter("applicant", applicant)
                            .getResultList();
    }
}

#### 服务层和业务逻辑

实现服务层接口和具体的业务逻辑,处理审批请求的提交、审批通过和审批拒绝:

// UserService.java
public interface UserService {
    User login(String username, String password);
    void register(User user);
}

// UserServiceImpl.java
public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public User login(String username, String password) {
        User user = userDao.findByUsername(username);
        if (user != null && user.getPassword().equals(password)) {
            return user;
        }
        return null; // 登录失败
    }

    @Override
    public void register(User user) {
        userDao.save(user);
    }
}

// ApprovalService.java
public interface ApprovalService {
    void submitRequest(User applicant, String requestText);
    List<ApprovalRequest> getRequestsByApplicant(User applicant);
    void approveRequest(Long requestId, User approver, String comment);
    void rejectRequest(Long requestId, User approver, String comment);
}

// ApprovalServiceImpl.java
public class ApprovalServiceImpl implements ApprovalService {
    private ApprovalRequestDao approvalRequestDao;

    public ApprovalServiceImpl(ApprovalRequestDao approvalRequestDao) {
        this.approvalRequestDao = approvalRequestDao;
    }

    @Override
    public void submitRequest(User applicant, String requestText) {
        ApprovalRequest request = new ApprovalRequest();
        request.setApplicant(applicant);
        request.setRequestText(requestText);
        request.setStatus(ApprovalStatus.PENDING);
        request.setCreatedAt(LocalDateTime.now());
        approvalRequestDao.save(request);
    }

    @Override
    public List<ApprovalRequest> getRequestsByApplicant(User applicant) {
        return approvalRequestDao.findByApplicant(applicant);
    }

    @Override
    public void approveRequest(Long requestId, User approver, String comment) {
        ApprovalRequest request = approvalRequestDao.findById(requestId);
        if (request != null && request.getStatus() == ApprovalStatus.PENDING) {
            request.setStatus(ApprovalStatus.APPROVED);
            request.setApprovedAt(LocalDateTime.now());
            request.setApprover(approver);
            request.setApprovalComment(comment);
            approvalRequestDao.save(request);
        } else {
            throw new IllegalArgumentException("Invalid request or status for approval.");
        }
    }

    @Override
    public void rejectRequest(Long requestId, User approver, String comment) {
        ApprovalRequest request = approvalRequestDao.findById(requestId);
        if (request != null && request.getStatus() == ApprovalStatus.PENDING) {
            request.setStatus(ApprovalStatus.REJECTED);
            request.setApprovedAt(LocalDateTime.now());
            request.setApprover(approver);
            request.setApprovalComment(comment);
            approvalRequestDao.save(request);
        } else {
            throw new IllegalArgumentException("Invalid request or status for rejection.");
        }
    }
}

#### 安全性和权限控制

对于安全性和权限控制,可以使用Spring Security等框架来管理用户的登录和访问权限,确保系统安全性。

### 总结

以上代码示例涵盖了一个基本的OA审批系统的关键部分:用户管理、审批流程设计(包括提交、审批通过和审批拒绝)、数据持久化等。在实际开发中,还需根据具体需求进一步扩展和优化,例如增加审批流程状态转移的复杂性、加强安全性措施等。希望这些示例能够帮助你理解如何构建一个完整的OA审批系统。

为了增加审批流程状态转移的复杂性和加强安全性措施,我们可以在之前的代码基础上进行进一步的扩展和优化。下面是一些建议:

### 增加审批流程状态转移的复杂性

1. **审批流程状态扩展**:
   - 引入更多的审批状态,例如中间状态(如等待复核、已撤销等),并相应地调整数据库表和实体类。

2. **状态转移规则**:
   - 实现更复杂的状态转移逻辑,例如审批通过后是否允许撤销、拒绝后是否可以再次提交等。

3. **审批链设计**:
   - 对于复杂的组织结构,考虑设计审批链,确保请求能够正确流转到需要的审批人员。

### 加强安全性措施

1. **密码安全**:
   - 使用密码哈希和盐值进行加密存储,可以考虑使用BCrypt或Argon2等安全的加密算法。

2. **身份验证**:
   - 引入多因素身份验证(MFA)机制,提升用户登录的安全性。

3. **权限控制**:
   - 使用细粒度的权限控制,确保用户只能访问其权限范围内的资源。可以结合框架如Spring Security来实现角色和权限的管理。

4. **数据保护**:
   - 使用SSL/TLS保护数据传输,对敏感数据进行加密存储和传输。

### 代码示例更新

#### 审批流程状态扩展

```java
// ApprovalStatus.java
public enum ApprovalStatus {
    PENDING, APPROVED, REJECTED, CANCELLED, UNDER_REVIEW // 示例:增加了取消和复核状态
}
```

#### 安全性增强

```java
// UserDaoImpl.java - 密码加密存储示例
@Override
public void save(User user) {
    user.setPassword(passwordEncoder.encode(user.getPassword())); // 使用密码加密器加密密码
    entityManager.getTransaction().begin();
    entityManager.persist(user);
    entityManager.getTransaction().commit();
}

// UserServiceImpl.java - 登录方法示例
@Override
public User login(String username, String password) {
    User user = userDao.findByUsername(username);
    if (user != null && passwordEncoder.matches(password, user.getPassword())) {
        return user;
    }
    return null; // 登录失败
}
```

### 总结

通过增加审批流程的状态复杂性和加强安全性措施,可以使OA审批系统更加健壮和安全。在实施时,根据具体需求和系统规模,还可以进一步调整和优化这些措施,确保系统在长期运行中能够满足安全和功能性的要求。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/31564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

芜湖市各地企业技术中心补助指南 附镜湖鸠江技术中心申报奖励+认定条件周期+流程

芜湖市各地企业技术中心申报周期 省企业技术中心的认定&#xff0c;原则上每年进行一次。各市经济和信息化主管部门根据省经济和信息化厅通知要求报送申请材料&#xff0c;受理截止日期以当年工作通知为准。 芜湖市各地企业技术中心补助汇编 市级&#xff08;2023年兑现政策…

电商项目测试实战之购物车页面用例设计

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、购物车页面 二、购物车页面测试范围列表 三、购物车页面功能点需求分析 四、部分功能点的测试…

vscode CMAKE 配置调试

概述 记录使用VSCODE中的CMAKE拓展构建项目时出现的报错 CMakePresets.json&#xff1a; {"version": 6,"configurePresets": [{"name": "x64-debug","displayName": "x64-debug","cmakeExecutable":…

Hi3861 OpenHarmony嵌入式应用入门--中断按键

本篇讲解gpio的中断使用方式。 硬件原理图如下&#xff0c;与上一篇一样的电路 GPIO API API名称 说明 hi_u32 hi_gpio_init(hi_void); GPIO模块初始化 hi_u32 hi_io_set_pull(hi_io_name id, hi_io_pull val); 设置某个IO上下拉功能。 hi_u32 hi_gpio_set_dir(hi_gpio_…

cefsharp 修改请求头request.Headers,以实现某种请求验证(v100+已测试)含主要源码和注释

(一)目的:cefsharp实现修改请求头 Tip:网上搜的很多代码都无法实现(要么版本较低,方法有变,要么就行不通),较多的错误是:集合属性只读。其中一个bili网友的测试方法注解一张图,但没有具体代码。参考一下。 (二)实现方法 2.1 创建对象 ChromiumWebBrowser home…

数据库精选题(二)(引言+关系代数)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;数据库 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 前言 常见概念 一、什么是数据库&#xf…

axi4 总线之 axi-full 学习记录

ARSIZE&#xff1a;读突发大小&#xff0c;给出每次突发传输的字节数支持 1、2、4、8、16、32、64、128 ARSIZE 字节数3b00013b00123b01043b01183b100163b101323b110643b111128 ARLEN&#xff1a;8 位&#xff0c;读传输的突发长度。 AXI3 只支持1~16次的突发传输&#xff08;B…

【Git】撤销远程仓库的提交(push)

参考&#xff1a;Git 撤销远程仓库的提交&#xff08;push&#xff09;和本地仓库的提交&#xff08;commit&#xff09;_git 撤销远程提交-CSDN博客 git reset --soft 想要撤销后的版本号 git push origin master -f soft 要撤销的本地代码不会变化&#xff0c;只是git仓库指…

神舟电脑怎么清理缓存文件?介绍几种简单有效方法

随着日常使用神舟电脑的时间增长&#xff0c;各种缓存文件、临时文件以及无用的数据会逐渐堆积&#xff0c;这不仅占据了宝贵的磁盘空间&#xff0c;还可能拖慢系统的运行速度&#xff0c;影响我们的使用体验。因此&#xff0c;定期清理神舟电脑中的缓存文件变得至关重要。本文…

Vue3插件安装

一、volar插件安装 volar&#xff1a;Vue文件的语法提示和高亮提醒。volar已经更名为Vue - Official&#xff0c;其安装步骤如下。 (1)打开vscode&#xff0c;点击扩展面板&#xff0c;在搜索窗口中输入volar&#xff0c;选择Vue - Official进行安装。 &#xff08;2&#xff0…

hpcpack指定节点计算

HPCPack是微软的高性能计算(HPC)解决方案之一&#xff0c;它可以用于在指定的集群节点上进行计算任务。在使用HPCPack时&#xff0c;你可以通过指定节点名称来限制任务运行的位置。 以下是一个示例&#xff0c;展示了如何在HPCPack作业脚本中指定节点计算&#xff1a; <?…

AJAX中get和post的区别

在AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;中&#xff0c;GET 和 POST 是两种常用的HTTP请求方法&#xff0c;它们之间存在一些关键的区别。以下是这些区别的主要点&#xff1a; 请求的目的&#xff1a; GET&#xff1a;通常用于从服务器检索&#xff08;…

如何使用gprof对程序进行性能分析

如何使用gprof对程序进行性能分析 目录 1 gprof概述 2 gprof原理简述 3 gprof使用 3.1 gprof使用简述 3.2 gprof使用示例 4 小结 1 gprof概述 gprof 是 一个 GNU 的程序性能分析工具&#xff0c;可以用于分析C\C程序的执行性能。gprof工具可以统计出各个函数的调用次数、执…

【React篇】useMemo和useCallback的区别

useMemo 和 useCallback 是 React Hooks 中的两个常用函数&#xff0c;它们主要用于优化性能。尽管它们有一些相似之处&#xff0c;但它们的用途和行为有所不同。 useMemo: useMemo 用于在组件渲染时根据提供的依赖项“记忆”一个值。这意味着如果依赖项没有改变&#xff0c;u…

什么是 vCPU?有什么作用

vCPU 是物理 CPU 的虚拟化版本&#xff0c;是云计算的基本组成部分。这些虚拟化计算单元的一大优势是其良好的可扩展性&#xff0c;这也是它们在云托管中发挥重要作用的原因。 vCPU 有什么作用? vCPU(虚拟中央处理器)是物理CPU的虚拟化变体。换句话说&#xff0c;vCPU 是虚拟机…

慎用 np.vstack 和 np.hstack

连接2个array&#xff0c;如果是1维数组&#xff0c;要用 np.hstack&#xff0c;2维数组&#xff0c;要用 np.vstack。 但可以统一用 np.concatenate(, axis0)。 >>> import numpy as np >>> anp.random.randn(3) >>> a array([-0.38378444, 0.…

邀请函 | 桥田智能出席AMTS展会 家族新成员正式发布

作为国际汽车制造技术与装备及材料专业展览会&#xff0c;AMTS将于2024年7月3-5日在上海新国际博览中心举行。本届展会以【向“新”而行 “智”领未来】为主题&#xff0c;聚焦汽车及新能源全产业链&#xff0c;围绕“车身工程、部件工程、新能源三电工程及未来汽车开发”等技…

重塑W来|暴雨携手英特尔®单路最强“芯”加速数智创新应用

近日&#xff0c;极“至”能&#xff0c;重塑“W”来—英特尔单路最强“芯”XeonW 方案研讨会在贵阳成果举办&#xff0c;行业精英们共聚一堂&#xff0c;了解Xeon W处理器的最新进展、卓越性能和多元应用场景&#xff0c;并针对最新的行业趋势、技术创新以及战略规划进行深入…

90 岁老人靠一辆自行车年赚 170 亿,捷安特如何打造山地车极致产品力?

一位富家小开在中年时经商失败&#xff0c;38岁时从零开始创业&#xff0c;最终在自行车整车市场占据了70%的份额&#xff0c;他是怎么做到的&#xff1f; 一家曾为美国自行车品牌代工的台湾工厂&#xff0c;成功从ToB转型为ToC业务&#xff0c;从90%的代工业务转变为全球最大…

QT 中charts各种图表的综合应用

此文章是根据Qt之QChart各个图表的简单使用&#xff08;含源码注释&#xff09;-CSDN博客进行的简单优化。 这里面用了几种数值轴QT 数值型坐标轴有那些&#xff1f;&#xff08;QValueAxis&#xff09;-CSDN博客&#xff0c;对图例进行了一定的设置&#xff0c;还有多个相同控…