人力资源管理系统项目流程

首先来说一下权限数据库的设计

RBAC是一种访问控制模型,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。

1、hr表是用户表,存放了用户的基本信息

2、role表是角色表,根据springsecurity的规范,里面有个name字段表示角色的英文名称。

3、menu表是一张资源表,登陆成功后根据用户的动态加载需要的模块,用户表里面有个url字段,表示一个url pattern,根据路径匹配规则,发出一个admin/user的请求,会被admin/**拦截到,系统再去查看这规则对应的角色是哪些,然后再去查看改用户是否具备相应的角色,进而判断请求是否合法

说到判断用户的角色,就要说到动态处理角色和资源的关系了

用户认证通过Provider来做,所以Provider需要拿到系统已经保存的认证信息,其中UserDetails用来拿到用户的信息,有几个方法需要在Hr类中实现,其中一个是isenable方法判断用户是不是被禁用,还有一个方法叫做getAuthorities,这方法用来获取当前用户所具有的角色

注:即直接从 roles 中获取当前用户所具有的角色,构造 SimpleGrantedAuthority 然后返回即可。

UserDetails

从上面可以知道最终交给Spring Security的是。该接口是提供用户信息的核心接口。该接口实现仅仅存储用户的信息。后续会将该接口提供的用户信息封装到认证对象中去。默认提供了:

用户的权限集, 默认需要添加前缀用户的加密后的密码,

不加密会使用前缀

应用内唯一的用户名

账户是否过期

账户是否锁定

凭证是否过期

用户是否可用

在配置类中添加了两个自定义拦截器 JwtLoginFilter 和 JwtTokenFilter,JwtLoginFilter 继承了 UsernamePasswordAuthenticationFilter理表单提交的身份信息。                                          封装了凭证后进行登陆信息的校验。用户认证的管理类,所有的认证请求(比如login)都会通过提交一个token给AuthenticationManagerauthenticate()方法来实现, 跳转到 JwtAuthenticationProvider.authenticate 中进行逻辑处理,校验成功则会调用 JwtLoginSuccessHandler.生成一个token并返回给用户。

JwtTokenFilter判断当前请求的角色是否有访问当前路径的权限,校验当前用户是否具备所需要的角色。校验通过,则允许访问,否则抛出 AccessDeniedException 异常。

然后再自定义权限拦截FileterInvocationSecurityMetadataSource有一个默认的实现类DefaultFilterInvocationSecurityMetadataSource。功能就是通过当前的请求地址,获取该地址需要的用户角色

自定义 UrlAccessDecisionManager 类实现 AccessDecisionManager 接口 访问决策管理器         判断当前请求的角色是否有访问当前路径的权限

 配置webSecurityConfig

  1. 在 configure(HttpSecurity http) 方法中,将刚刚创建的 权限拦截,访问决策管理器 ,注入进来。到时候,请求都会经过刚才的过滤器(除了 configure(WebSecurity web)方法忽略的请求)。
  2. successHandler 中配置登录成功时返回的 JSON,登录成功时返回当前用户的信息。
  3. failureHandler 表示登录失败,登录失败的原因可能有多种,我们根据不同的异常输出不同的错误提示即可。

 登录和注册都要密码加密加盐 通过 BCryptPasswordEncoder 中的 encode 方法对密码进行处理

部门的数据库设计和存储过程

        

DELIMITER $$ //设置存储结构的结束符号

USE `vhr`$$  //使用vhr库

DROP PROCEDURE IF EXISTS `addDep`$$   //如果存在删除

CREATE DEFINER=`root`@`localhost` PROCEDURE `addDep`(in depName varchar(32),in parentId int,in enabled boolean,out result int,out result2 int)
begin
  declare did int;                       //定义did整数型
  declare pDepPath varchar(64);          //pdeppath varchar
  insert into department set name=depName,parentId=parentId,enabled=enabled; //插入name id enable
  select row_count() into result;  //返回修改的行数
  select last_insert_id() into did;  //最后插入的id
  set result2=did;                     //刚刚的id赋值给result2
  select depPath into pDepPath from department where id=parentId;  //查找父类depath值赋给pdepath 
  update department set depPath=concat(pDepPath,'.',did) where id=did;//设置depath的值
  update department set isParent=true where id=parentId;      //让父类的isparent为true
end$$

DELIMITER ;
  1. 该存储过程接收五个参数,三个输入参数分别是部门名称、父部门 Id,该部门是否启用,两个输出参数分别表示受影响的行数和插入成功后 id 的值。
  2. 存储过程首先执行插入操作,插入完成后,将受影响行数赋值给 result。
  3. 然后通过 last_insert_id() 获取刚刚插入的 id,赋给 result2。
  4. 接下来查询父部门的 depPath,并且和刚刚生成的id组合后作为刚刚插入部门的 depPath。
  5. 将父部门的 isParent 字段更新为 true。

删除部门的存储结构

DELIMITER $$

USE `vhr`$$

DROP PROCEDURE IF EXISTS `deleteDep`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `deleteDep`(in did int,out result int)
begin                                         //输入 did 输出 result
  declare ecount int;                         //定义ecout 
  declare pid int;                            //定义pid
  declare pcount int;                         //定义pcount
  select count(*) into ecount from employee where departmentId=did; //ecount=did的数量
  if ecount>0 then set result=-1;             //如果 ecount>0则result=-1
  else 
  select parentId into pid from department where id=did; //设置pid=父部门
  delete from department where id=did and isParent=false;   //删除id和is设置为fasle的条
  select row_count() into result;                            //返回result受影响的行数
  select count(*) into pcount from department where parentId=pid; //返回pcount=夫部门的行数
  if pcount=0 then update department set isParent=false where id=pid; //如果父部门为0 然后设置 isparent和设置 id=
  end if;
  end if;
end$$

DELIMITER ;
  1. 一个输入参数表示要删除数据的 id,一个输出参数表示删除结果。
  2. 如果该部门下有员工,则该部门不能被删除。
  3. 删除该部门时注意加上条件 isParent=false,即父部门不能被删除,这一点我在前端已经做了判断,正常情况下父部门的删除请求不会被发送,但是考虑到前端的数据不能被信任,所以后台我们也要限制。
  4. 删除成功之后,查询删除部门的父部门是否还有其他子部门,如果没有,则将父部门的 isParent 修改为 false。

整合RabbitMq实现邮件发送

1.用户提交注册信息后,将消息提交给队列,让后队列将发送邮件通知给用户

导入rabbitmq依赖和mail依赖。thymeleaf依赖,server依赖,在添加员工的实现类

然后再rabbitmqconfig里面配置消息队列和topic

交换机 

生产者

1.Producer先连接到Broker,建立连接Connection,开启一个信道(Channel)。

2.Producer声明一个交换器并设置好相关属性。

3.Producer声明一个队列并设置好相关属性。

4.Producer通过路由键将交换器和队列绑定起来。

5.Producer发送消息到Broker,其中包含路由键、交换器等信息。

6.相应的交换器根据接收到的路由键查找匹配的队列。

7.如果找到,将消息存入对应的队列,如果没有找到,会根据生产者的配置丢弃或者退回给生产者。

8.关闭信道。

消费者

1.Producer先连接到Broker,建立连接Connection,开启一个信道(Channel)。

2.向Broker请求消费响应的队列中消息,可能会设置响应的回调函数。

3.等待Broker回应并投递相应队列中的消息,接收消息。

4.消费者确认收到的消息,ack

5.RabbitMq从队列中删除已经确定的消息。

6.关闭信道。

7.关闭连接。

9.管理连接。

然后在添加员工的实现类添加邮件通知。

最后添加监听邮件,如果邮件发送失败的话,会重新入队

         

easyPOI导入和到处excel文件

在employee实体类中添加excel注解。其中有个nation民族的类里面有id属性,然后就写mapper查询员工,增加导出员工数据的接口,以流的形式输出

 导入员工数据

导入员工数据也是以io的数据传入的,用list遍历增加员工的数据,最后使用savebatch比较列表是不是添加成功的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值