layui 可以商用吗_基于Spring Boot和layui的RBAC权限管理系统:前端项目

操作文档

[TOC]

部署文档

依赖环境

IDE编译器:IDEA 2020.1

Redis: 随意版本

Maven: 随意版本

PostgreSQL:PostgreSQL 12(随意版本也行)

Nginx: 随意版本

JDK: 1.8

修改配置文件

只需修改web模块下的application.yml配置文件

spring:

datasource:

## 连接地址

url: jdbc:postgresql://localhost:5432/postgres?currentSchema=public

## 数据库用户名

username: postgres

## 数据库密码

password: postgres

redis:

database: 0

## Redis默认无密码,都是默认配置

port: 6379

host: localhost

server:

## 访问端口

port: 8080

servlet:

## url访问前缀

context-path: /mrc

## 日志

logging:

## 修改日志存储路径,本机运行可以删掉

file:

path: C:/Users/Administrator/Desktop/Git/mrc-log/my.log

level:

root: INFO

Redis缓存

缓存@Cacheable 的 Value集中放在util模块下的com.mrc.SysCacheValue

使用interface进行分类

interface下的成员变量是==全局变量==,以下代码

public interface DICT {

// 字典类型

String TYPE = "dice_type";

// 字典值

String VALUE = "dict_value";

}

等同于,原理请百度去

public interface DICT {

// 字典类型

public static final String TYPE = "dice_type";

// 字典值

public static final String VALUE = "dict_value";

}

@CacheEvict简单讲解,allEntries = true意思是属于这个value的缓存全部删除

beforeInvocation = true是在执行下面的代码前就执行删除缓存

@CacheEvict(value = '', allEntries = true, beforeInvocation = true)

Sql数据还原

确保正确安装PostgreSQL 12

打开PostgresSQL客户端pgAdmin4

默认使用public架构

右键public

.%5Cpic%5C%E6%8D%95%E8%8E%B73.JPG

选择备份文件

.%5Cpic%5C%E6%8D%95%E8%8E%B74.JPG

选择文件

.%5Cpic%5C%E6%8D%95%E8%8E%B75.JPG

点击还原,大多数都能成功还原。

Nginx配置

安装好Nginx并测试,自行百度去

安装完成后,打开Nginx安装文件夹,打开conf,用记事本打开nginx.conf,修改以下文件

#user nobody;

worker_processes 1;

#error_log logs/error.log;

#error_log logs/error.log notice;

#error_log logs/error.log info;

#pid logs/nginx.pid;

events {

worker_connections 1024;

}

http {

include mime.types;

default_type application/octet-stream;

underscores_in_headers on; # 开启请求头下划线支持

client_max_body_size 30m; # 上传文件最大限制

proxy_connect_timeout 600; # 设置超时时间

proxy_read_timeout 600;

proxy_send_timeout 600;

sendfile on;

keepalive_timeout 65;

server {

listen 8081; # 本地Nginx端口

server_name localhost;

location / {

root C:/Users/Administrator/Desktop/Git/work/html; # 前端页面路径

index index.html index.htm;

}

location ^~ /mrc/ { # 服务端访问前缀

proxy_pass http://localhost:8080; # 后端访问地址

proxy_redirect off;

proxy_set_header Host $http_host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Cookie $http_cookie;

}

}

}

修改完成后重启或开启nginx,重启命令 nginx.exe -s reload

测试是否能打开目标页面,不行自行==百度==去

服务端规范

主要构成

Spring boot 2.X、 MyBatis 、PostgreSQL 12、Redis、maven、Nginx

Maven多模块介绍

.%5Cpic%5C%E6%8D%95%E8%8E%B7.JPG

本系统基于Maven多模块搭建,各模块直接的依赖如上图,也可查看对应模块的pom.xml文件查看依赖关系,其中work-sheet是根模块,一切模块都依赖它。

web负责controller,service负责业务,dao负责与数据库打交道,domain是实体类,rbac是系统鉴权中心,conf是配置中心,util是各种工具类

MyBatis-Plus

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

代码生成器

代码生成器在项目中的位置:dao模块中的 com.mrc.CodeGenerator.java

使用方法

在CodeGenerator.java中找到以下代码段,修改参数,支持多表生产

/**

* 填入需要生成的表的表名,支持 String...,填入多个表名

*/

strategy.setInclude("");

填好后运行main程序,自动生成entity、dao、service、serviceImpl、controller

==注意:==再生成代码完成后,手动将dao模块下的com.mrc.mapper.xml中的xml文件==剪切==到dao模块中的resources中的xml文件夹中,不然不能运行自定义的sql语句

单表操作可以不用自定义SQL语句,直接在对应的controller编写业务逻辑,各种业务场景可参考web模块的com.mrc.controller.TestController

实体类(domain)规则

可参考domain模块中的com.mrc.entity.Test

==代码生成器==生成的model,需在class文件上加上@JsonInclude(JsonInclude.Include.NON_NULL),作用是值为Null字段不会是被JSON序列号

在标记为ID的属性上加上@JsonSerialize(using = ToStringSerializer.class),==只适用在ID字段为Long属性的字段==,加上后JSON序列化返回前端时会变成String类型

在标记为ID的属性上再加上@NotNull(message = "ID不能为空",groups = Update.class)

在==新增==时属性不能为空或者Null的属性加上@NotEmpty(message = "",groups = Insert.class),message是自定义信息,不会返回给用户看,只会打印在日志中,方便到时排查问题。

在==修改==时不能为空的属性属性加上@NotEmpty(message = "",groups = Insert.class)或@NotNull(message = "",groups = Insert.class),这些==注解==都是==Hibernate Validator==的注解,详情百度了解Hibernate Validator;

在==代码生成器==生成的createDate、modifyDate、isDelete字段上的@TableField注解中,加上该属性select = false,代表在使用MyBatis-Plus查询构造器时不查询该字段。

在自定义的各种dto,vo中,必须实现序列号接口并自定义序列化UID,必要时需按照第二,第三

implements Serializable

private static final long serialVersionUID=1L;

由于使用了lombok,IDEA需安装插件,File—》Settings—》Plugins—》搜索Lombok,并安装

IDEA插件推荐Rainbow Brackets、MyBatisX、Alibaba Java Coding Guidelines、Translastion

Lombok相关注解请自行百度

Accessors(chain = true)有此注解的实体类变为链式对象,实际应用如下

Test test = new Test()

.setId(123L)

.setName("名字")

.setIsDelete(0)

.setCreateDate(LocalDateTime.now())

.setModifyDate(LocalDateTime.of(2020, Month.JANUARY,20,12,20));

业务规则

在==业务类==或者==控制器类=上加上@Slf4j注解

所有需要@Autowired的统一采用构造器注入,例如下面这样子,不用在引用对象上加@Autowired

TestService service;

public TestController(TestService service) {

this.service = service;

}

在有业务错误时,例如==插入失败==,==更新失败==等业务上的错误,需在错误时打印错误日志,使用log.info(),方便错误回溯。错误时统一返回CommonEnum.INTERNAL_SERVER_ERROR错误信息,例子

@DeleteMapping("/{id}")

ResultBody remove(@PathVariable Long id) {

if (!service.removeById(id)) {

log.info("Test删除失败,失败id:{}",id);

return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);

}

return ResultBody.success();

}

统一RESTful接口风格,获取用GET,新增用POST,更新用PUT,删除用DELETE

命名规则

dao层命名规则

获取单个对象: selectXXXByXXX,例子:selectTestById(Long testId);

获取多个对象:selectXXXListByXXX,例子:selectTestListByName(String name);

分页获取多个对象:selectXXXPage(long page, long limit);

统计值:countXXX,例子:countTest();

插入新增: insert(Test test), batchInsert(List testList)

修改更新:updateByXXX或update,例子:updateById(Test test),update(Test test)

删除:deleteByXXX,例子:deleteById(Long id),deleteByIds(List id);

service接口命名规则

获取单个对象: getXXXByXXX,例子:getTestById(Long testId);

获取多个对象:getXXXListByXXX,例子:getTestListByName(String name);

分页获取多个对象:getXXXPage(long page, long limit);

统计值:countXXX,例子:countTest();

插入新增: save(Test test), batchSave(List testList)

修改更新:modifyByXXX或update,例子:modifyById(Test test),update(Test test)

删除:removeByXXX,例子:removeById(Long id),removeByIds(List id);

领域模型(domain)命名规则

基本对象:XXXX,例子:Test

数据传输对象(一般用于接收用户数据):xxxxDto,例子:TestDto

展示对象(一般用于分页数据表格):xxxVo,例子:TestVo

RBAC模块使用方法

在前端HTML新建好页面后,需要操作数据库的三个表,menu,interface,menu_interface来关联菜单与接口的关联。

.%5Cpic%5C%E6%8D%95%E8%8E%B72.JPG

---------------------------------------新增菜单--------------------------------------------

insert

into

public.menu(

id,

parent_id,

title,

check_arr,

"name",

icon,

jump,

"order"

)

values(

1260459079697305600,

1259738910347890688,

'测试',

0,

'',

'',

'',

0

);

---------------------------------------新增接口-------------------------------------------

insert

into

public.interface(

id,

title,

interface_alias

)

values(

1260459079718277120,

'',

''

),

(

1260459079743442944,

'',

''

),

(

1260459079764414464,

'鏇存柊',

'dict::update'

),

(

1260459079789580288,

'',

''

);

------------------------------------关联菜单与接口关系------------------------------------

insert

into

public.menu_interface(

id,

menu_id,

interface_id,

create_date

)

values(

1260459079814746112,

1260459079697305600,

1260459079718277120,

now()

),

(

1260459079839911936,

1260459079697305600,

1260459079743442944,

now()

),

(

1260459079865077760,

1260459079697305600,

1260459079764414464,

now()

),

(

1260459079890243584,

1260459079697305600,

1260459079789580288,

now()

);

以上ID为自己手动填入,自己手动一一对应

util模块包里的com.mrc.IdFactory有个main方法可以生产10个ID,

Menu菜单表

parent_id为-1的是一级菜单,必须设置title,icon

parent_id为父菜单ID时,它们就产生了关联,必须填写jump,title

order为排列顺序,最好从主页是1开始,到最后的设置,每一级菜单均需设置或者只设置一级菜单

Interface接口表

title命名规则

新增类型接口:【新增】

修改类型接口:【修改】

读取类型接口:【读取】

删除类型接口:【删除】

interface_alias命名规则

新增类型接口:【xxx::add】,例子 role::add

修改类型接口:【xxx::update】,例子 role::update

读取类型接口:【xxx::get】,例子 role::get

删除类型接口:【xxx::delete】,例子 role::delete

其他类型的自定义:【操作类::操作名称】,例子 user::resetPwd

权限别名常量类

在==interface表==新增了相关接口权限后,需在util模块下的com.mrc.Constant的Authorization下添加相关接口描述,参照已有例子新建;

/**

* 示例权限

*/

DEMO_ADD("demo::add"),

DEMO_GET("demo::get"),

DEMO_DELETE("demo::delete"),

DEMO_UPDATE("demo::update"),

Controller接口鉴权

在每个需要鉴权的接口加上@Authorization()注解

例子:

// 根据ID获取对象

@Authorization(Constant.Authorization.DEMO_GET)

@GetMapping("/{id}")

ResultBody getOne(@PathVariable Long id) {

return ResultBody.success(service.getById(id));

}

注解参数填写刚刚在com.mrc.Constant里面添加的对应常量

==Excel导入==数据工具类使用教程

在util模块下com.mrc.excel是Excel导入工具类

适用于用户适用Excel文件批量导入数据

支持 String,Short,Integer,Long,Date,暂时不支持 Float,Double

使用教程

新建一个Excel模板,并输入数据()这个括号是提示信息,必须是中文的括号,读取时会忽略

.%5Cpic%5Cexcel.JPG

新建一个实体类,这里偷懒用到了lombok,@ExcelId是标识数据库为主键的列,@Excel是对应Excel文件的列标题,不用加(),@ExcelId支持String和Long,默认使用雪花ID算法。

.%5Cpic%5Cexcel2.JPG

单元测试

@SpringBootTest(classes = WebApplication.class)

public class ExcelTest {

@Test

void ExcelRead() {

try {

File file = new File("C:\\Users\\Administrator\\Desktop\\Test.xlsx");

List list = ExcelRead.read(file, T.class);

list.forEach(System.out::println);

} catch (MyExcelException e) {

e.printStackTrace();

}

}

}

打印结果

spring_boot_layui_rbac_html

ExcelRead.read(File file, Class model)是静态方法,直接用

单元测试类放在web模块 —》test—》ExcelTest

==重点:==由于是提供给用户在Web页面上传,上传的文件是先保存到服务器后,再读取服务器上的Excel文件,读取完后默认==删除文件==。所有单元测试后,文件会被删除!修改逻辑请去

com.mrc.excel.ExcelRead中修改逻辑,里面的注释很完整的啦。

==感谢==,读取全靠它,我只负责装配工作

==Redis_Token==简介

在没开发Redis_Token这个基于Token的用户登录验证之前,用的是JWT(JSON WEB TOKEN),但在使用时发现有点问题

登录时间不能续期,过期了只能重新登录获取,也有很多解决方案,但都是要用户端更换Token。

在Token未过期时,用户登出后,Token依然有效。解决方案是加入黑名单。

复制Token,去JWT官网,可以解密,查看JWT存储的信息

所以基于JWT的特性,再结合Redis的特性,开发出一套小而精的登录鉴权

大致原理如下,对象信息是用的Redis的map数据类型存储。

有重复登录处理,逼退旧的,只给登录权限给最新登录的。

.%5Cpic%5Ctok.JPG

前端规范

ID唯一性

因为开启了==标签页功能==,请==务必==注意 ID 的冲突,尤其是在你自己绑定事件的情况。ID 的命令可以遵循以下规则来规避冲突:

LAY-路由-任意名

以消息中心页面为例,假设它的路由为:/app/message/,那么 ID 应该命名为:

删除

ID唯一性同样适用于lay-filter

数据表格页面规范

==最上面必须有==

操作日志

用户

操作日志

其他可参考src\views\demo\testDemo\list.html

JavaScript引用规范

统一采用以下这种方式引用JavaScript文件

layui.use('demo', layui.factory('demo'));

JavaScript文件必须这样定义

layui.define(['form', 'upload', 'table', 'aut'], function (exports) {

var $ = layui.$,

layer = layui.layer,

setter = layui.setter,

view = layui.view,

admin = layui.admin,

form = layui.form,

table = layui.table,

aut = layui.aut;

var ok = setter.response.statusCode.ok; // 200

var fail = setter.response.statusCode.fail; // 400

var error = setter.response.statusCode.error; // 500

var forbidden = setter.response.statusCode.forbidden;// 403

// 下面的demo对应HTML页面的layui.use('demo', layui.factory('demo'));

exports('demo', {});

})

==不得采用传统方式导入JavaScript文件==

数据表格JavaScript规范

数据表格代码

var myTable = table.render({// 生成一个引用对象,方便表格重载

elem: '#LAY-demo-testDemo-table', // 表格唯一ID

url: '/mrc/test', // 获取数据的URL,默认采用GET方式访问

page: true, // 开启分页

loading: true, // 开启分页加载层

title:"示例", // 定义 table 的大标题(在文件导出等地方会用到)

toolbar: true, // 开启工具条,可导出Excel

autoSort: false, // 关闭前端的排序,启动服务端的排序

headers: { // 加上Token请求头

access_token: layui.data('layuiAdmin').access_token

},

cols: [

[{

checkbox: true // 开启多选框,由于权限操作需要,关闭行操作按钮

},

{

field: 'id', // 对应属性名

title: 'ID' // 表头

}, {

field: 'name',

title: '用户名'

}, {

field: 'create_date', // 当需要开启服务端排序时,该字段填写数据库字段名

title: '时间',

align: 'center',

templet: function(d) { // 并采用templet返回该行数据

return util.toDateString(d.createDate)

},

sort: true

}

]

]

});

表格重载方法(封装成函数)

function table_reload() {

myTable.reload({ // 这里的myTable对象是上面数据表格生成的引用对象

url: '/mrc/test' // 重载地址,不用指定重载页数,默认当前页面数

})

}

表格搜索

// LAY-demo-testDemo-table-search-btn为搜索按钮的lay-filter值

form.on('submit(LAY-demo-testDemo-table-search-btn)', function (data) {

var field = data.field;

myTable.reload({ // 这里的myTable对象是上面数据表格生成的引用对象

url: '/mrc/test', // 重载地址,不用指定重载页数,默认当前页面数

where: field // 搜索对象

});

return false; // 当搜索的form为

则不需要加
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值