# 后台手册

# 分页实现

# 前端调用实现

参考前端调用实现

# 后台逻辑实现

参考后台逻辑实现

# 导入导出

在实际开发中经常需要使用导入导出功能来加快数据的操作。在项目中可以使用注解来完成此项功能。 在需要被导入导出的实体类属性添加@Excel注解,目前支持参数如下:

# 注解参数说明

参数 类型 默认值 描述
sort int Integer.MAX_VALUE 导出时在excel中排序,值越小越靠前
name String 导出到Excel中的名字
dateFormat String 日期格式, 如: yyyy-MM-dd
readConverterExp String 读取内容转表达式 (如: 0=男,1=女,2=未知)
separator String , 分隔符,读取字符串组内容
scale int -1 BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
roundingMode int BigDecimal.ROUND_HALF_EVEN BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
celltype Enum Type.STRING 导出类型(0数字 1字符串 2图片)
height String 14 导出时在excel中每个列的高度 单位为字符
width String 16 导出时在excel中每个列的宽 单位为字符
suffix String 文字后缀,如% 90 变成90%
defaultValue String 当值为空时,字段的默认值
prompt String 提示信息
combo String Null 设置只能选择不能输入的列内容
headerBackgroundColor Enum IndexedColors.GREY_50_PERCENT 导出列头背景色IndexedColors.XXXX
headerColor Enum IndexedColors.WHITE 导出列头字体颜色IndexedColors.XXXX
backgroundColor Enum IndexedColors.WHITE 导出单元格背景色IndexedColors.XXXX
color Enum IndexedColors.BLACK 导出单元格字体颜色IndexedColors.XXXX
targetAttr String 另一个类中的属性名称,支持多级获取,以小数点隔开
isStatistics boolean false 是否自动统计数据,在最后追加一行统计数据总和
type Enum Type.ALL 字段类型(0:导出导入;1:仅导出;2:仅导入)
align Enum HorizontalAlignment.CENTER 导出对齐方式HorizontalAlignment.XXXX
handler Class ExcelHandlerAdapter.class 自定义数据处理器
args String[] {} 自定义数据处理器参数

# 导出实现流程

1、前端调用方法(参考如下)

// 查询参数 queryParams
queryParams: {
  pageNum: 1,
  pageSize: 10,
  userName: undefined
},

/** 导出按钮操作 */
handleExport() {
  this.download('system/xxxx/export', {
	...this.queryParams
  }, `post_${new Date().getTime()}.xlsx`)
}
1
2
3
4
5
6
7
8
9
10
11
12
13

2、添加导出按钮事件

<el-button
  type="warning"
  icon="el-icon-download"
  size="mini"
  @click="handleExport"
>导出</el-button>
1
2
3
4
5
6

3、在实体变量上添加@Excel注解

@Excel(name = "用户序号", prompt = "用户编号")
private Long userId;

@Excel(name = "用户名称")
private String userName;
	
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
private String sex;

@Excel(name = "最后登陆时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date loginDate;
1
2
3
4
5
6
7
8
9
10
11

4、在Controller添加导出方法







 
 


@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize(hasPermi = "system:user:export")
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user) throws IOException
{
	List<SysUser> list = userService.selectUserList(user);
	ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
	util.exportExcel(response, list, "用户数据");
}
1
2
3
4
5
6
7
8
9

# 导入实现流程

参考导入实现流程

# 自定义标题信息

参考自定义标题信息

# 自定义数据处理器

参考自定义数据处理器

# 自定义隐藏属性列

参考自定义隐藏属性列

# 导出对象的子列表

参考导出对象的子列表

# 上传下载

首先创建一张上传文件的表,例如:

drop table if exists sys_file_info;
create table sys_file_info (
  file_id           int(11)          not null auto_increment       comment '文件id',
  file_name         varchar(50)      default ''                    comment '文件名称',
  file_path         varchar(255)     default ''                    comment '文件路径',
  primary key (file_id)
) engine=innodb auto_increment=1 default charset=utf8 comment = '文件信息表';
1
2
3
4
5
6
7

# 上传实现流程

参考上传实现流程

# 下载实现流程

参考下载实现流程

# 权限注解

认证注解权限控制

  • @RequiresLogin登录认证:只有登录之后才能进入该方法。
  • @RequiresPermissions权限认证:必须具有指定权限才能进入该方法。
  • @RequiresRoles角色认证:必须具有指定角色标识才能进入该方法

# @RequiresRoles

@RequiresRoles注解用于配置接口要求用户拥有某(些)角色才可访问,它拥有两个参数

参数 类型 描述
value String[] 角色列表
logical Logical 角色之间的判断关系,默认为Logical.AND

示例1: 以下代码表示必须拥有admin角色才可访问

 





@RequiresRoles("admin")
public AjaxResult save(...)
{
    return AjaxResult.success(...);
}
1
2
3
4
5

示例2: 以下代码表示必须拥有admincommon角色才可访问

 





@RequiresRoles({"admin", "common"})
public AjaxResult save(...)
{
    return AjaxResult.success(...);
}
1
2
3
4
5

示例3: 以下代码表示需要拥有admincommon角色才可访问

 





@RequiresRoles(value = {"admin", "common"}, logical = Logical.OR)
public AjaxResult save(...)
{
    return AjaxResult.success(...);
}
1
2
3
4
5

# @RequiresPermissions

@RequiresPermissions注解用于配置接口要求用户拥有某(些)权限才可访问,它拥有两个参数

参数 类型 描述
value String[] 权限列表
logical Logical 权限之间的判断关系,默认为Logical.AND

示例1: 以下代码表示必须拥有system:user:add权限才可访问

 





@RequiresPermissions("system:user:add")
public AjaxResult save(...) 
{
    return AjaxResult.success(...);
}
1
2
3
4
5

示例2: 以下代码表示必须拥有system:user:addsystem:user:update权限才可访问

 





@RequiresPermissions({"system:user:add", "system:user:update"})
public AjaxResult save(...)
{
    return AjaxResult.success(...);
}
1
2
3
4
5

示例3: 以下代码表示需要拥有system:user:addsystem:user:update权限才可访问

 





@RequiresPermissions(value = {"system:user:add", "system:user:update"}, logical = Logical.OR)
public AjaxResult save(...)
{
    return AjaxResult.success(...);
}
1
2
3
4
5

提示

认证注解处理是有内定的处理顺序的,如果有个多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关) RequiresLogin、RequiresRoles、RequiresPermissions。
例如:你同时声明了RequiresRolesRequiresPermissions,那就要求拥有此角色的同时还得拥有相应的权限。

旧版使用方法

  1. 数据权限示例。
// 符合system:user:list权限要求
@PreAuthorize(hasPermi = "system:user:list")

// 不符合system:user:list权限要求
@PreAuthorize(lacksPermi = "system:user:list")

// 符合system:user:add或system:user:edit权限要求即可
@PreAuthorize(hasAnyPermi = { "system:user:add", "system:user:edit" })
1
2
3
4
5
6
7
8
  1. 角色权限示例。
// 属于user角色
@PreAuthorize(hasRole = "user")

// 不属于user角色
@PreAuthorize(lacksRole = "user")

// 属于user或者admin之一
@PreAuthorize(hasAnyRoles = { "user", "admin" })
1
2
3
4
5
6
7
8

# 编程式判断资源访问权限

示例: 编程式判断是否有资源权限

if (AuthUtil.hasPermi("sys:user:edit"))
{
    System.out.println("当前用户有编辑用户权限");
}
1
2
3
4

示例: 编程式判断是否有角色权限

if (AuthUtil.hasRole("admin"))
{
    System.out.println("当前用户有admin角色权限");
}
1
2
3
4

# 事务管理

参考事务管理实现

# 异常处理

参考异常处理实现

# 参数验证

参考参数验证

# 系统日志

参考系统日志实现

# 数据权限

参考数据权限实现

# 多数据源

在实际开发中,经常可能遇到在一个应用中可能需要访问多个数据库的情况,微服务版本采用了dynamic-datasource动态多数据源组件,使用参考:

1、对应模块pom加入ruoyi-common-datasource依赖

<!-- RuoYi Common DataSource -->
<dependency>
    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi-common-datasource</artifactId>
</dependency>
1
2
3
4
5

2、以ruoyi-system模块集成druid为例,配置主从数据库,其他数据源可以参考组件文档。

# spring配置
spring: 
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 5
        min-idle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,wall,slf4j
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      datasource:
          # 主库数据源
          master:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            username: root
            password: password
          # 从库数据源
          # slave:
            # url: 
            # username: 
            # password: 
            # driver-class-name: 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

3、ruoyi-common-datasource定义数据源注解,对应datasource配置的不同数据源节点

项目默认了主MasterSlave注解可以直接使用,其他的可以根据项目实际情况去添加。

4、使用注解在需要切换数据源的方法上或类上。

@Master
public void insertA()
{
	return xxxxMapper.insertXxxx();
}

@Slave
public void insertB()
{
	return xxxxMapper.insertXxxx();
}
1
2
3
4
5
6
7
8
9
10
11

在某些情况您可能需要手动切换数据源

DynamicDataSourceContextHolder.push("slave"); // 手动切换
....业务逻辑
DynamicDataSourceContextHolder.clear();
1
2
3

# 代码生成

参考代码生成实现

# 定时任务

参考定时任务实现

# 系统接口

参考系统接口实现

# 国际化支持

# 后台国际化流程

参考后台国际化流程

# 前端国际化流程

参考前端国际化流程

# 新建子模块

Maven多模块下新建子模块流程案例。

1、在ruoyi-modules下新建业务模块目录,例如:ruoyi-test

2、在ruoyi-test业务模块下新建pom.xml文件以及src\main\javasrc\main\resources目录。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-modules</artifactId>
        <version>x.x.x</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
	
    <artifactId>ruoyi-modules-test</artifactId>

    <description>
        ruoyi-modules-test系统模块
    </description>
	
    <dependencies>
    	
    	<!-- SpringCloud Alibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <!-- SpringCloud Alibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        
    	<!-- SpringCloud Alibaba Sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        
    	<!-- SpringBoot Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
		
        <!-- Mysql Connector -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        
        <!-- Ruoyi Common Security -->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common-security</artifactId>
        </dependency>
        
        <!-- Ruoyi Common Swagger -->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common-swagger</artifactId>
        </dependency>
		
		<!-- RuoYi Common Log -->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common-log</artifactId>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
   
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

3、在ruoyi-modules目录下pom.xml模块节点modules添加业务模块

<module>ruoyi-test</module>
1

4、src/main/resources添加bootstrap.yml文件

# Tomcat
server:
  port: 9301

# Spring
spring: 
  application:
    # 应用名称
    name: ruoyi-test
  profiles:
    # 环境配置
    active: dev
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

5、com.ruoyi.test包下添加启动类

package com.ruoyi.test;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;

/**
 * 测试模块
 * 
 * @author ruoyi
 */
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringCloudApplication
public class RuoYiTestApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RuoYiTestApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  测试模块启动成功   ლ(´ڡ`ლ)゙  \n" +
                " .-------.       ____     __        \n" +
                " |  _ _   \\      \\   \\   /  /    \n" +
                " | ( ' )  |       \\  _. /  '       \n" +
                " |(_ o _) /        _( )_ .'         \n" +
                " | (_,_).' __  ___(_ o _)'          \n" +
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
                " |  | \\ `'   /|   `-'  /           \n" +
                " |  |  \\    /  \\      /           \n" +
                " ''-'   `'-'    `-..-'              ");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34