权限管理开发:

数据库表设计

详细表的设计:

  • 每个表都有自己的主键字段尽量定义为NOT NULL

  • 尽量为每个字段添加备注

  • 数据库字段统一小写,单词之间使用下划线分隔

  • 使用InnoDB存储引擎

  • 可以使用varchar的字段尽可能不使用TEXT、BLOB类型表字符集选择UTF8

    技术实现:

    开发工具: idea

    jdk: 8

    后端:框架:spring mvc + mybatis

    缓存: redis

    数据库: mysql: 8.0.22

    前端:

详细数据库结构表设计:

image-20210812193312433

​ RBAC是基于角色的访问控制( Role-Based Access Control )在RBAC中,权限与角色相关联,用户 通过扮演适当的角色从而得到这些角色的权限。这样管理都是层级相互依赖的,权限赋予给角色,角色 又赋予用户,这样的权限设计很清楚,管理起来很方便

image-20210812193506584

image-20210813194639180

image-20210813194647591

image-20210813194703862

表设计:

角色表:sys_ role

image-20210813194735832

部门表:sys_acl表image-20210827112712555

模块表:sys_acl_module 层级目录树

image-20210827112637591

用户表:sys_user

image-20210827112902026

用户角色表:sys_user_role

image-20210827112920589

项目环境搭建

1、springMVC搭建:

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
```xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<springframework.version>5.3.9</springframework.version>

</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--springmvc-->

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--与spring版本一致-->

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
```

2、mysql配置

数据库驱动:
1
2
3
4
5
6
<!--      mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
数据库连接池:
1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>

web.xml配置:

image-20210827101128353

image-20210827101152614

image-20210827101206015

image-20210827101216217

java -jar mybatis-generator-core-1.3.2.jar -configfile gegenerator.xml -overwrite

核心类的生成:

generator生成代码:

需要工具:

generator生成:

image-20210827151511260

导入maven:

1
2
3
4
5
6
7
```xml
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
```

导入对应的jar包的依赖:

1
2
3
4
5
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>

修改一下命令以及生成对应的包位置:

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动包位置 -->
<classPathEntry location="/adora_plant/generator/mysql-connector-java-8.0.22.jar" /> <!-- 1 -->
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 数据库链接URL、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/wz?characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;zeroDateTimeBehavior=convertToNull&amp;serverTimezone=Asia/Shanghai" userId="root" password="jin200727"> <!-- 2 -->
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成模型的包名和位置 --> <!-- 3 -->
<javaModelGenerator targetPackage="com.dorou.model" targetProject="/adora_plant/generator/src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成的映射文件包名和位置 --> <!-- 4 -->
<sqlMapGenerator targetPackage="com.dorou.mapper" targetProject="/adora_plant/generator/src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 生成DAO的包名和位置 --> <!-- 5 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.dorou.dao" targetProject="/adora_plant/generator/src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 要生成那些表(更改tableName和domainObjectName就可以) --><!-- 6 -->
<table tableName="sys_acl" domainObjectName="SysAcl" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_acl_module" domainObjectName="SysAclModule" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_dept" domainObjectName="SysDept" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_log" domainObjectName="SysLog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_role" domainObjectName="SysRole" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_role_acl" domainObjectName="SysRoleAcl" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_user" domainObjectName="SysUser" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
<table tableName="sys_user_role" domainObjectName="SysRoleUser" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
</context>
</generatorConfiguration>

项目json 类的的定义,page:

JsonData:

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
package com.dorou.common;

/**
* 该类是对数据json形式的规范,当controller不需要去寻找视图时,以json形式返回值
* ret用来给前端判断是正常还是异常的请求
* 如果是false,将通过msg是什么原因出错
*/
public class JsonData {
private boolean ret;
private String msg;
private Object data;

public JsonData(boolean ret){
this.ret = ret;
}

// 定义全局方法:
// 成功时返回的数据
public static JsonData success(Object object,String msg){
JsonData jsonData = new JsonData(true);
jsonData.data = object;
jsonData.msg =msg;
return jsonData;
}
//返回成功时,可以携带自定义msg
public static JsonData success(Object object){
JsonData jsonData = new JsonData(true);
jsonData.data = object;
return jsonData;
}

//返回成功时,可以携带自定义msg
public static JsonData success(){
return new JsonData(true);
}
// 发生错误时返回的信息
public static JsonData fail(String msg){
JsonData jsonData = new JsonData(false);
jsonData.msg = msg;
return jsonData;
}


public boolean isRet() {
return ret;
}

public JsonData setRet(boolean ret) {
this.ret = ret;
return this;
}

public String getMsg() {
return msg;
}

public JsonData setMsg(String msg) {
this.msg = msg;
return this;
}

public Object getData() {
return data;
}

public JsonData setData(Object data) {
this.data = data;
return this;
}

@Override
public String toString() {
return "JsonData{" +
"ret=" + ret +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}

定义全局异常处理类:

1
2
3
4
5
6
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jsp-api</artifactId>
<version>6.0.53</version>
</dependency>

我们定义在我们说有的管理中,我们区别是json请求还是page 请求,需要进行区分,并且在我们使用自定义的请求的时候,如何能够抛出自己的异常

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
package com.dorou.common;

import com.dorou.exception.PermissionException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author jinweizhuo
* 如果spring管理,就会被它所捕捉到
*/
@Slf4j
public class SpringExceptionResolver implements HandlerExceptionResolver {
// 数据请求,页面请求
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
String url = httpServletRequest.getRequestURI().toString();
ModelAndView modelAndView ;
String defaultMsg = "System error";
// 数据请求与页面请求做区别,规范
// .json .page
// 要求项目中所有的json数据都要要求.json 页面 .page
if(url.endsWith(".json")){
// 如果是自定义异常,就需要直接抛出
if (e instanceof PermissionException){
JsonData result = JsonData.fail(e.getMessage());
// 将对象转换为map,ModelAndView 的异常返回值与正常返回值保持一致
// 为什么是jsonView ? spring-servlet.xml 配置里保持一致
modelAndView = new ModelAndView("jsonView",result.toMap());
}else {
log.error("unknow json exception,url" +url ,e);
JsonData result = JsonData.fail(defaultMsg);
modelAndView = new ModelAndView("jsonView",result.toMap());
}
// 如果是页面请求,处理异常
}else if (url.endsWith(".page")){
log.error("unknow page exception,url" +url ,e);
JsonData result = JsonData.fail(defaultMsg);
// 去找jsp里面定义的views exception的页面
modelAndView = new ModelAndView("exception",result.toMap());
} else {
log.error("unknow exception,url" +url ,e);
JsonData result = JsonData.fail(defaultMsg);
modelAndView = new ModelAndView("jsonView",result.toMap());
}

return modelAndView;
}
}

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
package com.dorou.exception;

import com.alibaba.druid.sql.visitor.functions.If;

/**
* @author jinweizhuo
*自定义异常
*/
public class PermissionException extends RuntimeException{
public PermissionException() {
super();
}

public PermissionException(String message) {
super(message);
}

public PermissionException(String message, Throwable cause) {
super(message, cause);
}

public PermissionException(Throwable cause) {
super(cause);
}

protected PermissionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

工具开发:

校验工具 -validator 请求传过来时对参数的处理,通过注解进行参数校验

json转换工具 - jackson convert 将对象转换为json数据进行传递

获取Spring上下文 -applicationContext 通过该类获取管理的bean

Http请求监听 -interceptor 对请求进行监听

用户相关管理

部门列表开发:

用户相关管理:

功能列表:新增、修改 删除部门

用户修改:分页信息展示

新增部门参数: