若依-原理

1.代码生成器

1.1源码分析

代码生成器分为两个部分:

第一部分涉及将业务表结构导入到系统中

第二部分是点击生成按钮,系统将根据表结构生成相应的前后端代码,并提供下载。

1.表结构说明

gen_table:存储业务表的基本信息 ,它对应于配置代码基本信息和生成信息的页面

gen_table_column:存储业务表的字段信息 它对应于配置代码字段信息的页面。

这两张表是一对多的关系,一张业务表可以有多个字段的信息,所以在字段信息表中有个外键table_id指向

2.目录结构

3.查询数据库列表

当管理员在界面上点击导入按钮时,会弹出一个对话框,此时,前端需要向后端发送请求,查询数据库并返回到前端,展示当前项目库中所有待导入的业务表。

<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
		select table_name, table_comment, create_time, update_time from information_schema.tables
		where table_schema = (select database())
		AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
		AND table_name NOT IN (select table_name from gen_table)
		<if test="tableName != null and tableName != ''">
			AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
		</if>
		<if test="tableComment != null and tableComment != ''">
			AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
		</if>
		<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
			AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
		</if>
		<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
			AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
		</if>
        order by create_time desc
	</select>

4.导入表结构

当管理员对话框中选中需要导入的业务表,点击确定按钮,此时,前端需要向后端发送请求,保存业务表的基本信息和字段信息

5.生成代码

6.问题分析

(1)每次生成代码都需要修改作者,去除实体类前缀过于繁琐,现在我们可以修改generator.yml配置文件来调整为自己项目的

(2)实体类支持Lombok,Controller类支持Swagger

需要Velocity模板引擎

1.2Velocity模版引擎

Velocity是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据 , 填充到模板中,从而实现界面和java代码的分离 !

1.基础语法

Velocity中的变量有两类

  • 在模板中定义变量: #set开头,比如 #set($name = "velocity")

  • 获取变量的的值: $name 或者 ${name}

获取对象中的数据

循环

循环遍历普通集合

循环遍历对象

if判断

在条件判断中,velocity支持常见的关系操作符,比如:&&(与), ||(或), !(非)

2.Lombok集成

(1)导入坐标(已完成)

dkd-common模块的pom.xml中添加lombok坐标

(2)修改模板

dkd-generator模块的domain.java.vm模板中添加lombok注解

修改完成之后,重启项目,找到代码生成的功能,通过代码预览可以查看实体类的代码:

3.Swagger集成

(1)修改模板

dkd-generator模块的 controller.java.vm模板中添加Swagger注解

返回结果改为R<>

2.RBAC权限控制

Spring Security是一个功能强大的Java安全框架,它提供了全面的安全认证和授权的支持。

1)认证(Authentication) 在Spring Security的世界里,认证就像用户登录时提交的用户名和密码,系统通过这些信息来验证“你是谁”。

2)授权(Authorization) 授权是确认用户在通过认证之后,是否有权限执行某些操作或访问特定资源。

2.1SpringSecurity配置

Spring Security的配置类是实现安全控制的核心部分

开启Spring Security各种功能,以确保Web应用程序的安全性,包括认证、授权、会话管理、过滤器添加等。

2.2用户登录流程

ruoyi-framework模块中com.ruoyi.framework.web.service.SysLoginService类的login方法处理登录逻辑

  1. 验证码校验

  2. 登录前置校验

  3. SS认证管理器用户校验,调用执行UserDetailsServiceImpl.loadUserByUsername

    1. 认证通过后,创建登录用户对象LoginUser包括用户ID、部门ID、用户信息和用户权限信息

  4. 登录成功,记录日志

  5. 修改用户表更新登录信息

  6. 生成token

2.3获取用户角色和权限

ruoyi-framework模块中com.ruoyi.framework.web.service.SysPermissionService

  1. getRolePermission查询该用户角色集合

  2. getMenuPermission查询该用户权限(菜单)集合用set集合,一个用户可能有多个角色,多个角色的权限可能有重复的

页面权限

2.4获取动态菜单路由

2.5权限注解

1.源码分析

在若依框架中,权限的验证最核心的是使用的Spring Security的提供的权限注解`@PreAuthorize `

- @PreAuthorize 是 Spring Security 框架中提供的一个安全注解,用于实现基于注解的访问控制。它允许开发者在**方法级别**上声明特定的安全约束,以确保只有满足指定条件的用户才能调用该方法

- 当 @PreAuthorize 注解被应用于某个方法时,Spring Security 在**该方法执行前**会先对当前认证的用户进行权限检查。如果检查通过,方法调用得以继续;否则,框架会抛出相应的权限异常(如 AccessDeniedException),阻止方法执行。

2.权限方法

3.公开接口

如果有些接口是不需要验证权限可以公开访问的,这个时候就需要我们给接口放行。

使用注解方式,只需要在Controller的类或方法上加入@Anonymous该注解即可

3.异步任务管理器

主要用于处理一些不需要即时返回结果的后台任务,从而提高应用程序的整体性能

// 多线程执行任务me()创建单例对象(饿汉式)
AsyncManager.me().execute(AsyncFactory.createTimerTask());

若依异步任务管理器是一个单例对象使用了线程池+异步工厂(产生任务用)

  • com.dkd.framework.manager.AsyncManager 异步任务管理器

  • com.dkd.framework.manager.factory.AsyncFactory 异步线程工厂

1、 AsyncManager.me()获取AsyncManager对象

2、调用execute方法,执行TimerTask任务(记录登录日志),它实现了runnable接口,由线程Thread去执行

3、execute方法内部调用ScheduledExecutorService异步操作任务调度线程池的schedule方法用于延迟10毫秒执行一个任务

4.操作日志

在需要被记录日志的controller方法上添加@Log注解,使用方法如下:

@Log(title = "订单管理", businessType = BusinessType.INSERT)
public AjaxResult add(...)
{
    return toAjax(...);
}

若依操作日志使用了自定义注解+AOP切面+异步任务管理器

  • com.ruoyi.common.annotation.Log 自定义注解

  • com.ruoyi.framework.aspectj.LogAspect 在一个aop切面类

    • 通过实现AOP切面编程,对目标方法进行拦截(标注Log注解的方法),实现了操作日志的自动记录

    • 异步任务管理器来将任务(记录操作日志到数据库)交给线程池来完成

5.定时任务

5.1源码分析

1.表结构说明

sys_job 表(一):这是核心的定时任务表,用于存储定时任务的配置信息,如任务名称、任务组、执行的类全名、执行的参数、cron表达式等

sys_job_log 表(多):用于记录定时任务的执行日志,包括任务的开始执行时间、结束执行时间、执行结果等

2.Quartz体系结构

3.Quartz核心API

4.定时任务执行

5.添加定时任务

6.定时任务状态修改

刚才我们分析新增定时任务的源码时,发现了任务在初始化时是处于暂停状态的。

如果要启动任务,可以在页面进行任务状态的开关控制,所以接下来我们对此功能的源码进行分析

5.2集群模式

首先我们来聊下为什么需要quartz集群

在单机模式下,默认所有的jobDetailtrigger都存储在内存中。这样做的好处是读取速度快,但缺点也很明显:一旦服务器故障,所有的任务数据就会丢失,这就是所谓的单点故障问题。

还有如果在一个高峰时段,比如上午9点,需要触发500个任务,这将给服务器带来巨大的负载压力。这不仅影响性能,还可能引发服务中断。

缺点:单点故障、负载压力大

为了解决这些问题,我们可以部署多个服务器节点,将任务信息存储到数据库中。这样,多个节点就可以通过共享数据库来协调任务的执行,形成Quartz集群模式。

这种方式不仅解决了单点故障问题,还能通过负载均衡提升效率。

集群模式的优势

  • 高可用性:即使某个节点出现问题,其他节点仍然可以正常运行。

  • 负载均衡:将任务分散到不同的节点执行,避免单个节点过载。

实现

1.导入sql

将若依提供的quartz.sql导入到数据库中

2.开启配置

打开dkd-quartz模块中ScheduleConfig配置类注释

3.节点复制

首先修改当前SpringBoot的启动类的名称

我们再添加(复制)一个SpringBoot的启动配置

-Dserver.port=8081

4.观察数据库

重启项目即可,观察数据库,已存入jobDetail和trigger,多个服务器节点可以实现共享

6.数据权限

在系统中,权限的分配和控制主要依赖于角色。每个角色可以被赋予不同的菜单权限和数据权限,用户则通过他们的角色来继承这些权限,进而决定他们能访问哪些系统资源。

目前,系统支持以下五种数据权限类型:

  • 全部数据权限:无限制访问所有数据,相当于拥有最高权限的通行证。

  • 自定数据权限:用户可以根据自己的需求设定访问特定数据的规则。

  • 部门数据权限:只能访问自己所在部门的数据,限制在本部门范围内。

  • 部门及以下数据权限:可以访问自己部门及下属部门的数据,适用于管理层级。

  • 仅本人数据权限:只能访问和操作自己的数据,保障个人隐私和数据隔离。

1.源码

1、若依系统的数据权限设计主要通过用户、角色、部门表建立关系,实现对数据的访问控制:

2、在需要数据权限控制方法上添加@DataScope注解,其中du用来表示表的别名

3、在mybatis查询底部标签添加数据范围过滤

其作用就是相当于在一个 select 语句后面拼接一个 and 条件语句,来实现查询限制

若依数据权限底层使用了自定义注解+AOP切面+SQL拼接

  • com.dkd.common.annotation.DataScope 自定义注解

  • com.ruoyi.framework.aspectj.DataScopeAspect:切面类

    • 通过实现AOP编程,对目标方法进行拦截(标注DataScope 注解的方法),实现了构建数据范围SQL过滤条件

仅实体继承`BaseEntity`才会进行处理,`SQL`语句会存放到`BaseEntity`对象中的`params`属性中,然后在`xml`中通过`${params.dataScope}`获取拼接后的语句。

2.改造

需求

我们有一个系统登录日志,里面记录了所有用户的登录信息。

但是,并不是所有人都应该看到所有的日志数据。所以,我们需要根据用户的角色来控制他们能查看的数据范围。

(1)添加权限注解

dkd-system模块的com.dkd.system.service.impl.SysLogininforServiceImpl在服务层的方法上使用 @DataScope 注解

(2)添加表字段

如果sys_logininfo业务表需要实现数据权限,需要有dept_iduser_id这两个字段。

(3)添加实体属性

dkd-system模块的com.dkd.system.domain.SysLogininfor实体类中,需要有deptIduserId这两个属性。

(4)修改映射文件

dkd-system模块的com.dkd.system.domain.SysLogininforMapper.xml映射文件中,通过动态拼接 SQL,实现数据范围的过滤

(5)异步工厂调整

dkd-framework模块的com.dkd.framework.manager.factory.AsyncFactory异步工厂创建登录日志任务时,需要有deptIduserId这两个属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值