今日内容
- 数据库设计
- 部门管理
- 用户管理
- 模块管理
- RBAC权限模式
- 角色管理
第一章 数据库设计( 理解 )
1. 多租户数据库设计
1.1 多租户技术介绍
传统软件模式,指客户通过买断的方式获取软件,将软件部署在企业内部,不同的企业各自部署一套自己的软件系统
SaaS模式,指客户购买的是软件提供出来的服务而不是软件,软件统一部署到服务提供商的服务器上,用户只有使用权
那么在SaaS模式下,就要考虑到如何保证多个用户数据存储的隔离和安全问题,这样就有了多租户技术
多租户技术是一种软件架构技术,目的是确保多个用户信息存储在一个数据中心的情况下,数据的隔离和安全问题。
简单讲:在一台服务器上运行应用实例为多个用户提供服务,并且要尽量保证多用户数据的隔离。
1.2 多租户数据库设计方案
目前基于多租户的数据库设计方案通常有如下三种:
- 独立服务器、独立库:每个租户一个数据库服务器
- 共享服务器、独立库:多个租户使用同一个数据库服务器,但是每个租户一个数据库
- 共享服务器、共享库:租户数据同库同表,使用特定标识区分数据所属租户
三种方案对比下来:开发、部署、维护的成本依次降低,数据的安全、隔离性依也次降低
在SAAS-Export平台中,处于教学的目的,采用的是共享服务器、共享库方式设计。
2. 数据库设计三范式与反三范式
范式指的是数据库表的设计规则,好的设计可以减少数据冗余,提高硬盘利用率
2.1 三范式(1970 硬盘贵)
- 第一范式(1NF):确保每一列的原子性,做到每列不可拆分(每一列都表述一个独立完整内容)
- 第二范式(2NF):每张表只描述一件事
- 第三范式(3NF):消除推导关系(凡是可以通过其它列推导出来的列就不要再出现在数据表的设计中 ,计算结果等内容)
2.2 反三范式(用户体验 贵)
反三范式是基于第三范式所调整的,它指的是: 有时为了提高查询效率,可以适当保留冗余数据
3. 数据库建模
了解了数据的设计思想,那对于数据库表的表设计应该怎么做呢?答案是数据库建模
数据库建模:在设计数据库时,对现实世界进行分析、抽象、并从中找出内在联系,进而确定数据库的结构。它主要包括两部分内容:确定最基本的数据结构;对约束建模。
3.1 建模工具
对于数据模型的建模,最有名的要数PowerDesigner,PowerDesigner是在中国软件公司中非常有名的,其易用性、功能、对流行技术框架的支持、以及它的模型库的管理理念,都深受设计师们喜欢。他的优势在于:不用在使用create table等语句创建表结构,数据库设计人员只关注如何进行数据建模即可,将来的数据库语句,可以自动生成
3.2 使用PD建模
(1) 选择新建数据库模型
打开PowerDesigner,文件->建立新模型->model types(选择类型)->Physical Data Model(物理模型)
(2) 控制面板
(3) 创建数据库表
点即面板按钮中的创建数据库按钮创建数据库模型:
切换columns标签,可以对表中的所有字段进行配置
(4) 导出sql
菜单->数据库(database)->生成数据库表结构(GenerateDatabase)
第二章 部门管理
1. 需求和分析
1.1 需求描述
对部门进行基本CRUD操作
1.2 数据模型分析
2. 代码实现
2.1 domain
在domain模块的com.itheima.domain.system
包下建立Dept
类
@Data
public class Dept implements Serializable {
private String id;
private String deptName;
private Dept parent;//注意这个字段, 代表的是父部门
private Integer state;
private String companyId;
private String companyName;
}
2.2 dao
在dao模块的com.itheima.dao.system
包下建立DeptDao
接口
package com.itheima.dao.system;
import com.itheima.domain.system.Dept;
import java.util.List;
/**
* 创建dao接口
*/
public interface DeptDao {
/**
* 查询列表
*/
// 此id用于做企业隔离
List<Dept> findAll(String companyId);
void save(Dept dept);
Dept findById(String id);
void update(Dept dept);
void deleteById(String id);
}
在dao模块的resources/com/itheima/dao/system
包下建立DeptDao.xml
文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.system.DeptDao">
<!--自定义结果集映射-->
<resultMap id="BaseResultMap" type="com.itheima.domain.system.Dept">
<id property="id" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<result property="state" column="state"/>
<result property="companyId" column="company_id"/>
<result property="companyName" column="company_name"/>
<!--这个有问题 暂时不处理-->
<!-- <result property="parent" column="parent_id"/>-->
</resultMap>
<update id="update">
update pe_dept
<set>
<if test="deptName != null and deptName != ''">
dept_name=#{deptName},
</if>
<if test="parent.id != null and parent.id != ''">
parent_id=#{parent.id},
</if>
<if test="state != null">
state=#{state},
</if>
<if test="companyId != null and companyId != ''">
company_id=#{companyId},
</if>
<if test="companyName != null and companyName != ''">
company_name=#{companyName},
</if>
</set>
where dept_id = #{id}
</update>
<delete id="deleteById">
delete from pe_dept where dept_id = #{id}
</delete>
<select id="findAll" resultMap="BaseResultMap">
select * from pe_dept where company_id = #{companyId}
</select>
<select id="findById" resultMap="BaseResultMap">
select * from pe_dept where dept_id = #{id}
</select>
<insert id="save">
insert into pe_dept (
dept_id,
dept_name,
parent_id,
state,
company_id,
company_name
) values (
#{id},
#{deptName},
#{parent.id},
#{state},
#{companyId},
#{companyName}
);
</insert>
</mapper>
2.3 service
在service模块的com.itheima.service.system
包下建立DeptService
接口
package com.itheima.service.system;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.Dept;
import java.util.List;
public interface DeptService {
List<Dept> findAll(String companyId);
void save(Dept dept);
Dept findById(String id);
void update(Dept dept);
void deleteById(String id);
PageInfo findByPage(String companyId, Integer pageNum, Integer pageSize);
}
在service模块的com.itheima.service.system.impl
包下建立DeptServiceImpl
实现类
package com.itheima.service.system.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.dao.system.DeptDao;
import com.itheima.domain.system.Dept;
import com.itheima.service.system.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptDao deptDao;
@Override
public List<Dept> findAll(String companyId) {
return deptDao.findAll(companyId);
}
@Override
public void save(Dept dept) {
deptDao.save(dept);
}
@Override
public Dept findById(String id) {
return deptDao.findById(id);
}
@Override
public void update(Dept dept) {
deptDao.update(dept);
}
@Override
public void delete(String id) {
deptDao.deleteById(id);
}
@Override
public PageInfo findByPage(String companyId,Integer pageNum, Integer pageSize) {
//1. 设置pageNum和pageSize
PageHelper.startPage(pageNum,pageSize);
//2. 调用一个查询所有的方法
List<Dept> list = deptDao.findAll(companyId);
//3. 直接返回PageInfo
return new PageInfo(list,10);
}
}
3. 部门列表
3.1 代码开发
在web模块的com.itheima.web.controller.system
包下建立DeptController
类
package com.itheima.web.controller.system;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.Dept;
import com.itheima.service.system.DeptService;
import com.itheima.web.controller.BaseController;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.UUID;
@Controller
@RequestMapping("/system/dept")
public class DeptController extends BaseController {
//todo 模拟一下企业Id和企业name,等到登录之后,再改成真的
public String getCompanyId() {
return "1";
}
public String getCompanyName() {
return "大脸猫皮具外贸有限公司";
}
@Autowired
private DeptService deptService;
@RequestMapping(value = "/list", name = "部门列表查询")
public String list(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo pageInfo = deptService.findByPage(getCompanyId(), pageNum, pageSize);
request.setAttribute("page", pageInfo);
return "/system/dept/dept-list";
}
}
3.2 父部门不显示
3.2.1 问题分析
3.2.2 解决方案
<association property="parent" column="parent_id" select="findById" />
4. 新增部门
4.1 代码开发
@RequestMapping(value = "/toAdd", name = "跳转部门新增页面")
public String toAdd() {
//1. 查询所有部门
List<Dept> deptList = deptService.findAll(getCompanyId());
request.setAttribute("deptList",deptList);
return "/system/dept/dept-add";
}
//新增和修改统一用一个方法处理
@RequestMapping(value = "/edit", name = "部门新增")
public String edit(Dept dept) {
if (StringUtils.isEmpty(dept.getId())) {
//1. 设置主键
dept.setId(UUID.randomUUID().toString());
//2. 设置企业信息
dept.setCompanyId(getCompanyId());
dept.setCompanyName(getCompanyName());
deptService.save(dept);
} else {
deptService.update(dept);
}
//重定向到list方法
return "redirect:/system/dept/list.do";
}
4.2 新增顶级部门时报错
4.2.1 问题分析
Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`saas-export`.`pe_dept`, CONSTRAINT `SYS_C005596` FOREIGN KEY (`parent_id`) REFERENCES `pe_dept` (`dept_id`))
问题定位:
如果新增或者更新为顶级部门, 前台传递的parent_id为"", 而这一列有外键约束, 不能为"" 但是可以为null
4.2.2 解决方案
/**
* 新增,修改功能
*/
@RequestMapping(value = "/edit", name = "部门新增")
public String edit(Dept dept) {
// 如果父id为"",设置为null
if (StringUtils.isEmpty(dept.getParent().getId())){
dept.getParent().setId(null);
}
if (StringUtils.isEmpty(dept.getId())) {
//1. 设置主键
dept.setId(UUID.randomUUID().toString());
//2. 设置企业信息
dept.setCompanyId(getCompanyId());
dept.setCompanyName(getCompanyName());
deptService.save(dept);
} else {
deptService.update(dept);
}
//重定向到list方法
return "redirect:/system/dept/list.do";
}
5. 修改部门
5.1 代码开发
@RequestMapping(value = "/toUpdate", name = "跳转部门编辑页面")
public String toUpdate(String id) {
//1. 根据id查询当前部门信息
Dept dept = deptService.findById(id);
request.setAttribute("dept", dept);
//2. 查询所有部门
List<Dept> deptList = deptService.findAll(getCompanyId());
request.setAttribute("deptList", deptList);
//3. 转发到修改页面
return "/system/dept/dept-update";
}
5.2 修改部门为顶级部门时失败
5.2.1 问题分析
5.2.1 解决方案
去掉此项的非空判断
<update id="update">
update pe_dept
<set>
<if test="deptName != null and deptName != ''">
dept_name=#{deptName},
</if>
parent_id=#{parent.id},
<if test="state != null">
state=#{state},
</if>
<if test="companyId != null and companyId != ''">
company_id=#{companyId},
</if>
<if test="companyName != null and companyName != ''">
company_name=#{companyName},
</if>
</set>
where dept_id = #{id}
</update>
6. 删除部门
6.1 代码开发
@RequestMapping(value = "/delete", name = "部门删除")
public String delete(String id) {
//调用service删除
deptService.deleteById(id);
//重定向到list方法
return "redirect:/system/dept/list.do";
}
6.2 如果一个部门有子部门, 删除报错
6.2.1 问题分析
由于部门表是自关联的设计。就表示我们在直接删除父部门时成功了,子部门数据其实就变成了孤儿,所以外键会约束,不让删除
6.2.2 解决方案
- 在删除部门数据时,做一个判断,如果该部门有子部门,做出友情提示,不允许删除…【异步实现 课下作业】
- 级联操作: 连同子(孙子)部门一起删除
补充知识:
CASCADE: 父表delete、update的时候,子表会delete、update掉关联记录;
SET NULL: 父表delete、update的时候,子表会将关联记录的外键字段所在列设为null,所以注意在设计子表时外键不能设为not null;
RESTRICT: 如果想要删除父表的记录时,而在子表中有关联该父表的记录,则不允许删除父表中的记录;
NO ACTION:同 RESTRICT,也是首先先检查外键;
第三章 用户管理
1. 需求和分析
对用户进行基本CRUD操作
2. 代码实现
2.1 domain
在domain模块的com.itheima.domain.system
包下建立User
类
package com.itheima.domain.system;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class User implements Serializable {
private String id; // 用户id
private String deptId; // 部门id
private String email; // 邮箱
private String userName; //用户名
private String station; // 职务名称
private String password; // 密码
private String state; // 状态 1:可用、0:不可用
private String companyId; // 企业id
private String companyName; // 企业名称
private String deptName; // 部门名称
private String managerId; // 上级id
private String gender; // 性别
private String telephone; // 手机号
private String birthday; // 生日
/*
0-saas管理员
1-企业管理员
2-总经理
3-部门经理
4-普通员工
*/
private Integer degree; // 等级
private Double salary; // 工资
private String joinDate; // 入职日期
private Integer orderNo; // 排序号
private String createBy; // 创建人
private String createDept; // 创建人所在部门
private Date createTime; // 创建时间
private String updateBy; // 更新人
private Date updateTime; // 更新时间
private String remark; // 备注
}
2.2 dao
在dao模块的com.itheima.domain.system
包下建立UserDao
接口
public interface UserDao {
List<User> findAll(String companyId);
void save(User user);
User findById(String id);
void update(User user);
void delete(String id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.dao.system.UserDao">
<resultMap id="BaseResultMap" type="com.itheima.domain.system.User">
<id column="user_id" property="id"/>
<result column="dept_id" property="deptId"/>
<result column="email" property="email"/>
<result column="user_name" property="userName"/>
<result column="password" property="password"/>
<result column="state" property="state"/>
<result column="company_id" property="companyId"/>
<result column="company_name" property="companyName"/>
<result column="dept_name" property="deptName"/>
<result column="manager_id" property="managerId"/>
<result column="join_date" property="joinDate"/>
<result column="salary" property="salary"/>
<result column="birthday" property="birthday"/>
<result column="gender" property="gender"/>
<result column="station" property="station"/>
<result column="telephone" property="telephone"/>
<result column="degree" property="degree"/>
<result column="remark" property="remark"/>
<result column="order_no" property="orderNo"/>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select * from pe_user where company_id=#{companyId} order by order_no
</select>
<select id="findById" resultMap="BaseResultMap">
select * from pe_user where user_id = #{id}
</select>
<insert id="save">
insert into pe_user (user_id, dept_id, email, user_name, password, state, company_id,
company_name, dept_name, manager_id, join_date, salary, birthday,
gender, station, telephone, degree, remark, order_no)
values (#{id}, #{deptId}, #{email}, #{userName}, #{password}, #{state}, #{companyId},
#{companyName}, #{deptName}, #{managerId}, #{joinDate}, #{salary}, #{birthday},
#{gender}, #{station}, #{telephone}, #{degree}, #{remark}, #{orderNo})
</insert>
<update id="update">
update pe_user
<set>
<if test="deptId!=null and deptId!=''">
dept_id =#{deptId} ,
</if>
<if test="email!=null and email!=''">
email =#{email} ,
</if>
<if test="userName!=null and userName!=''">
user_name =#{userName} ,
</if>
<if test="station!=null and station!=''">
station =#{station} ,
</if>
<if test="password!=null and password!=''">
password =#{password} ,
</if>
<if test="state!=null and state!=''">
state =#{state} ,
</if>
<if test="companyId!=null and companyId!=''">
company_id =#{companyId} ,
</if>
<if test="companyName!=null and companyName!=''">
company_name=#{companyName} ,
</if>
<if test="deptName!=null and deptName!=''">
dept_name =#{deptName} ,
</if>
<if test="managerId!=null and managerId!=''">
manager_id =#{managerId} ,
</if>
<if test="gender!=null and gender!=''">
gender =#{gender} ,
</if>
<if test="telephone!=null and telephone!=''">
telephone =#{telephone} ,
</if>
<if test="birthday!=null and birthday!=''">
birthday =#{birthday} ,
</if>
<if test="degree!=null and degree!=''">
degree =#{degree} ,
</if>
<if test="salary!=null and salary!=''">
salary =#{salary} ,
</if>
<if test="joinDate!=null and joinDate!=''">
join_date =#{joinDate} ,
</if>
<if test="orderNo!=null and orderNo!=''">
order_no =#{orderNo} ,
</if>
<if test="createBy!=null and createBy!=''">
create_by =#{createBy} ,
</if>
<if test="createDept!=null and createDept!=''">
create_dept =#{createDept} ,
</if>
<if test="createTime!=null and createTime!=''">
create_time =#{createTime} ,
</if>
<if test="updateBy!=null and updateBy!=''">
update_by =#{updateBy} ,
</if>
<if test="updateTime!=null and updateTime!=''">
update_time =#{updateTime} ,
</if>
<if test="remark!=null and remark!=''">
remark =#{remark},
</if>
</set>
where user_id = #{id}
</update>
<delete id="delete">
delete from pe_user where user_id = #{id}
</delete>
</mapper>
2.3 service
在service模块的com.itheima.service.system
包下建立UserService
接口
package com.itheima.service.system;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.User;
import java.util.List;
public interface UserService {
List<User> findAll(String companyId);
void save(User user);
User findById(String id);
void update(User user);
void delete(String id);
PageInfo findByPage(String companyId, Integer pageNum, Integer pageSize);
}
在service模块的com.itheima.service.system.impl
包下建立UserServiceImpl
实现类(复制DeptServiceImpl,修改)
package com.itheima.service.system.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.dao.system.UserDao;
import com.itheima.domain.system.User;
import com.itheima.service.system.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> findAll(String companyId) {
return userDao.findAll(companyId);
}
@Override
public void save(User user) {
userDao.save(user);
}
@Override
public User findById(String id) {
return userDao.findById(id);
}
@Override
public void update(User user) {
userDao.update(user);
}
@Override
public void delete(String id) {
userDao.delete(id);
}
@Override
public PageInfo findByPage(String companyId,Integer pageNum, Integer pageSize) {
//1. 设置pageNum和pageSize
PageHelper.startPage(pageNum,pageSize);
//2. 调用一个查询所有的方法
List<User> list = userDao.findAll(companyId);
//3. 直接返回PageInfo
return new PageInfo(list,10);
}
}
3. UserController
在web模块的com.itheima.web.controller.system
包下建立UserController
类(复制DeptController,修改)
package com.itheima.web.controller.system;
import cn.hutool.core.lang.UUID;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.Dept;
import com.itheima.domain.system.User;
import com.itheima.service.system.DeptService;
import com.itheima.service.system.UserService;
import com.itheima.web.controller.BaseController;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
@RequestMapping("/system/user")
public class UserController extends BaseController {
//todo 模拟一下企业Id和企业name,等到登录之后,再改成真的
public String getCompanyId() {
return "1";
}
public String getCompanyName() {
return "大脸猫皮具外贸有限公司";
}
@Autowired
private UserService userService;
@Autowired
private DeptService deptService;
/**
* 生成列表
*/
@RequestMapping(value = "/list", name = "部门列表查询")
public String list(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo pageInfo = userService.findByPage(getCompanyId(), pageNum, pageSize);
request.setAttribute("page", pageInfo);
return "/system/user/user-list";
}
/**
* 跳转新增页面
*/
@RequestMapping(value = "/toAdd", name = "跳转部门新增页面")
public String toAdd() {
// 查询所在部门
List<Dept> deptList = deptService.findAll(getCompanyId());
request.setAttribute("deptList", deptList);
return "/system/user/user-add";
}
/**
* 新增,修改功能
*/
@RequestMapping(value = "/edit", name = "部门新增")
public String edit(User user) {
if (StringUtils.isEmpty(user.getId())) {
//1. 设置主键
user.setId(UUID.randomUUID().toString());
//2. 设置企业信息
user.setCompanyId(getCompanyId());
user.setCompanyName(getCompanyName());
userService.save(user);
} else {
userService.update(user);
}
//重定向到list方法
return "redirect:/system/user/list.do";
}
/**
* 跳转到修改
*/
@RequestMapping(value = "/toUpdate", name = "跳转部门编辑页面")
public String toUpdate(String id) {
//1. 根据id查询当前部门信息
User user = userService.findById(id);
request.setAttribute("user", user);
//2. 查询所有部门
List<Dept> deptList = deptService.findAll(getCompanyId());
request.setAttribute("deptList", deptList);
//3. 转发到修改页面
return "/system/user/user-update";
}
/**
* 删除功能
*/
@RequestMapping(value = "/delete", name = "部门删除")
public String delete(String id) {
//调用service删除
userService.delete(id);
//重定向到list方法
return "redirect:/system/user/list.do";
}
}
4. 问题处理
4.1 新增用户时密码问题
4.1.1问题分析
当前密码是明文入库的
4.1.2解决方案
md5 sha1
/**
* 将明文密码转成MD5密码
* 123456> e10adc3949ba59abbe56e057f20f883e
* 123456 > e10adc3949ba59abbe56e057f20f883e
* 特性:
* 恒等性: 多次对同一个字符串加密,得到的结果是一样的
* 定长输出: 无论输入的字符串长度为多少,输出的长度都是一致的32
* 雪崩效应: 输入的字符串,一旦出现一点点改变,结果大不一样
* 不可逆性: 无法根据加密之后的密码推导出加密之前的密码
*/使用MD5加密 + 加盐技术
public static void main(String[] args) {
// 加密工具类[密码,盐,散列次数]
String md5Pwd = new Md5Hash("123456", "abc@qq.com", 2).toString();
System.out.println(md5Pwd);
}
if (StringUtils.isNotEmpty(user.getPassword())){
String pwd = new Md5Hash(user.getPassword(),user.getEmail(),2).toString();
user.setPassword(pwd);
}
4.2 修改用户时密码问题
4.2.1 问题分析
进入修改页面的时候, 程序会把加密之后的密码返显到页面
如果我们在修改页面上, 修改了密码提交, 密码就又变成了明文入库了
4.2.1 解决方案
回显密码的时候,直接回显为空 当点击更新按钮之后, 做判断:
1 如果依旧为空, 代表用户不想修改密码 , 后台不做处理
2 如果不为空, 代表用户想修改密码 , 后台在修改方法中做加密处理
User user = userService.findById(id);
user.setPassword(null);
request.setAttribute("user", user);
第四章 代码优化
目前在UserController
和DeptController
中存在同一段代码,可以提取到BaseController
中
public class BaseController {
@Autowired
protected HttpServletRequest request;
@Autowired
protected HttpServletResponse response;
@Autowired
protected HttpSession session;
public String getCompanyId() {
return "1";
}
public String getCompanyName() {
return "大脸猫皮具外贸有限公司";
}
}
第五章 模块管理
1. 需求和分析
1.1 需求描述
1.2 模块的类型
这里的模块主要分为这样几种: 一级菜单、二级菜单、页面按钮
1.3 数据模型分析
模块是SaaS的人在管理,跟具体企业没有关系,所以不需要使用companyId区分
2. 代码复制
2.1 domain
@Data
public class Module implements Serializable {
private String id;
private String parentId;
private String parentName;
private String name;
private int layerNum;
private int isLeaf;
private String ico;
private String cpermission;
private String curl;
private String ctype;//主菜单 二级菜单 按钮
private String state;
private String belong;//属于SaaS还是企业
private String cwhich;
private int quoteNum;
private String remark;
private int orderNo;
}
2.2 dao
public interface ModuleDao {
List<Module> findAll();
void save(Module module);
Module findById(String id);
void update(Module module);
void delete(String id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.dao.system.ModuleDao" >
<resultMap id="BaseResultMap" type="com.itheima.domain.system.Module">
<id column="module_id" property="id"/>
<result column="parent_id" property="parentId"/>
<result column="parent_name" property="parentName"/>
<result column="name" property="name"/>
<result column="layer_num" property="layerNum"/>
<result column="is_leaf" property="isLeaf"/>
<result column="ico" property="ico"/>
<result column="cpermission" property="cpermission"/>
<result column="curl" property="curl"/>
<result column="ctype" property="ctype"/>
<result column="state" property="state"/>
<result column="belong" property="belong"/>
<result column="cwhich" property="cwhich"/>
<result column="quote_num" property="quoteNum"/>
<result column="remark" property="remark"/>
<result column="order_no" property="orderNo"/>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select * from ss_module order by ctype asc, order_no asc
</select>
<insert id="save">
insert INTO ss_module(
module_id,
parent_id,
parent_name,
name,
layer_num,
is_leaf,
ico,
cpermission,
curl,
ctype,
state,
belong,
cwhich,
quote_num,
remark,
order_no
)
VALUES (
#{id},
#{parentId},
#{parentName},
#{name},
#{layerNum},
#{isLeaf},
#{ico},
#{cpermission},
#{curl},
#{ctype},
#{state},
#{belong},
#{cwhich},
#{quoteNum},
#{remark},
#{orderNo}
)
</insert>
<update id="update">
update ss_module
<set>
<if test="parentId!=null and parentId!=''">
parent_id = #{parentId} ,
</if>
<if test="parentName!=null and parentName!=''">
parent_name= #{parentName} ,
</if>
<if test="name!=null and name!=''">
name = #{name} ,
</if>
<if test="layerNum!=null and layerNum!=''">
layer_num = #{layerNum} ,
</if>
<if test="isLeaf!=null and isLeaf!=''">
is_leaf = #{isLeaf} ,
</if>
<if test="ico!=null and ico!=''">
ico = #{ico} ,
</if>
<if test="cpermission!=null and cpermission!=''">
cpermission= #{cpermission} ,
</if>
<if test="curl!=null and curl!=''">
curl = #{curl} ,
</if>
<if test="ctype!=null and ctype!=''">
ctype = #{ctype} ,
</if>
<if test="state!=null and state!=''">
state = #{state} ,
</if>
<if test="belong!=null and belong!=''">
belong = #{belong} ,
</if>
<if test="cwhich!=null and cwhich!=''">
cwhich = #{cwhich} ,
</if>
<if test="quoteNum!=null and quoteNum!=''">
quote_num = #{quoteNum} ,
</if>
<if test="remark!=null and remark!=''">
remark = #{remark} ,
</if>
<if test="orderNo!=null and orderNo!=''">
order_no = #{orderNo} ,
</if>
</set>
where module_id=#{id}
</update>
<select id="findById" resultMap="BaseResultMap">
select * from ss_module where module_id=#{id}
</select>
<delete id="delete" >
delete from ss_module where module_id=#{id}
</delete>
</mapper>
2.3 service
public interface ModuleService {
List<Module> findAll();
void save(Module module);
Module findById(String id);
void update(Module module);
void delete(String id);
PageInfo<Module> findByPage(int pageNum, int pageSize);
}
package com.itheima.service.system.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.dao.system.ModuleDao;
import com.itheima.domain.system.Module;
import com.itheima.service.system.ModuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ModuleServiceImpl implements ModuleService {
@Autowired
private ModuleDao moduleDao;
@Override
public List<Module> findAll() {
return moduleDao.findAll();
}
@Override
public void save(Module module) {
moduleDao.save(module);
}
@Override
public Module findById(String id) {
return moduleDao.findById(id);
}
@Override
public void update(Module module) {
moduleDao.update(module);
}
@Override
public void delete(String id) {
moduleDao.delete(id);
}
public PageInfo<Module> findByPage(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<Module> list = moduleDao.findAll();
return new PageInfo<Module>(list, 5);
}
}
3. ModuleController
在web模块的com.itheima.web.controller.system
包下建立ModuleController
类
package com.itheima.web.controller.system;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.Module;
import com.itheima.service.system.ModuleService;
import com.itheima.web.controller.BaseController;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.UUID;
@Controller
@RequestMapping("/system/module")
public class ModuleController extends BaseController {
@Autowired
private ModuleService moduleService;
@RequestMapping(value = "/list", name = "模块列表查询")
public String list(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo pageInfo = moduleService.findByPage(pageNum, pageSize);
request.setAttribute("page", pageInfo);
return "/system/module/module-list";
}
@RequestMapping(value = "/toAdd", name = "跳转模块新增页面")
public String toAdd() {
//1. 查询所有模块
List<Module> moduleList = moduleService.findAll();
request.setAttribute("menus", moduleList);
return "/system/module/module-add";
}
@RequestMapping(value = "/toUpdate", name = "跳转模块编辑页面")
public String toUpdate(String id) {
//1. 根据id查询当前模块信息
Module module = moduleService.findById(id);
request.setAttribute("module", module);
//2. 查询所有模块
List<Module> moduleList = moduleService.findAll();
request.setAttribute("menus", moduleList);
//3. 转发到修改页面
return "/system/module/module-update";
}
//新增和修改统一用一个方法处理
@RequestMapping(value = "/edit", name = "模块新增")
public String edit(Module module) {
if (StringUtils.isEmpty(module.getId())) {
//1. 设置主键
module.setId(UUID.randomUUID().toString());
moduleService.save(module);
} else {
moduleService.update(module);
}
//重定向到list方法
return "redirect:/system/module/list.do";
}
@RequestMapping(value = "/delete", name = "模块删除")
public String delete(String id) {
//调用service删除
moduleService.delete(id);
//重定向到list方法
return "redirect:/system/module/list.do";
}
}
第六章 RBAC权限模型(理解)
RBAC(全称:Role-Based Access Control)基于角色的权限访问控制。
在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这角色的权限。这就极大地简化了权限的管理。
第七章 角色管理
1. 需求和分析
1.1 需求描述
实现角色的 CRUD 操作,角色也是不同的企业管理自己管理的,所以也需要companyId做数据隔离
1.2 数据模型分析
2. 代码复制
2.1 domain
@Data
public class Role implements Serializable {
private String id;
private String name;
private String remark;
private String companyId;
private String companyName;
private Integer orderNo;
private String createBy;
private String createDept;
private Date createTime;
private String updateBy;
private Date updateTime;
}
2.2 dao
public interface RoleDao {
List<Role> findAll(String companyId);
void save(Role role);
Role findById(String id);
void update(Role role);
void delete(String id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.dao.system.RoleDao" >
<resultMap id="BaseResultMap" type="com.itheima.domain.system.Role">
<id column="role_id" property="id"/>
<result column="name" property="name"/>
<result column="company_id" property="companyId"/>
<result column="company_name" property="companyName"/>
<result column="order_no" property="orderNo"/>
<result column="create_by" property="createBy"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_by" property="updateBy"/>
<result column="update_time" property="updateTime"/>
<result column="remark" property="remark"/>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select * from pe_role where company_id=#{companyId} order by order_no asc ,create_time desc
</select>
<insert id="save">
insert INTO pe_role(
role_id,
name,
company_id,
company_name,
order_no,
create_by,
create_dept,
create_time,
update_by,
update_time,
remark
)
VALUES (
#{id},
#{name} ,
#{companyId} ,
#{companyName} ,
#{orderNo} ,
#{createBy} ,
#{createDept} ,
#{createTime} ,
#{updateBy} ,
#{updateTime} ,
#{remark}
)
</insert>
<update id="update">
update pe_role
<set>
<if test="name!=null and name!=''">
name =#{name} ,
</if>
<if test="companyId!=null and companyId!=''">
company_id =#{companyId} ,
</if>
<if test="companyName!=null and companyName!=''">
company_name=#{companyName} ,
</if>
<if test="orderNo!=null and orderNo!=''">
order_no =#{orderNo} ,
</if>
<if test="createBy!=null and createBy!=''">
create_by =#{createBy} ,
</if>
<if test="createDept!=null and createDept!=''">
create_dept =#{createDept} ,
</if>
<if test="createTime!=null and createTime!=''">
create_time =#{createTime} ,
</if>
<if test="updateBy!=null and updateBy!=''">
update_by =#{updateBy} ,
</if>
<if test="updateTime!=null and updateTime!=''">
update_time =#{updateTime} ,
</if>
<if test="remark!=null and remark!=''">
remark =#{remark},
</if>
</set>
where role_id=#{id}
</update>
<select id="findById" resultMap="BaseResultMap">
select * from pe_role where role_id=#{id}
</select>
<delete id="delete" parameterType="string">
delete from pe_role where role_id=#{id}
</delete>
</mapper>
2.3 service
public interface RoleService {
List<Role> findAll(String companyId);
void save(Role role);
Role findById(String id);
void update(Role role);
void delete(String id);
PageInfo<Role> findByPage(String companyId, int pageNum, int pageSize);
}
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleDao roleDao;
@Override
public List<Role> findAll(String companyId) {
return roleDao.findAll(companyId);
}
@Override
public void save(Role role) {
roleDao.save(role);
}
@Override
public Role findById(String id) {
return roleDao.findById(id);
}
@Override
public void update(Role role) {
roleDao.update(role);
}
@Override
public void delete(String id) {
roleDao.delete(id);
}
public PageInfo<Role> findByPage(String companyId,int pageNum, int pageSize) {
PageHelper.startPage(pageNum,pageSize);
List<Role> list = roleDao.findAll(companyId);
return new PageInfo<Role>(list,5);
}
}
3. RoleController
package com.itheima.web.controller.system;
import cn.hutool.core.lang.UUID;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.system.Role;
import com.itheima.service.system.RoleService;
import com.itheima.web.controller.BaseController;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
@RequestMapping("/system/role")
public class RoleController extends BaseController {
@Autowired
private RoleService roleService;
/**
* 生成列表
*/
@RequestMapping(value = "/list", name = "角色列表查询")
public String list(
@RequestParam(defaultValue = "1", name = "page") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo pageInfo = roleService.findByPage(getCompanyId(), pageNum, pageSize);
request.setAttribute("page", pageInfo);
return "/system/role/role-list";
}
/**
* 跳转新增页面
*/
@RequestMapping(value = "/toAdd", name = "跳转角色新增页面")
public String toAdd() {
//1. 查询所有角色
List<Role> roleList = roleService.findAll(getCompanyId());
request.setAttribute("roleList",roleList);
return "/system/role/role-add";
}
/**
* 新增,修改功能
*/
//新增和修改统一用一个方法处理
@RequestMapping(value = "/edit", name = "角色新增")
public String edit(Role role) {
if (StringUtils.isEmpty(role.getId())) {
//1. 设置主键
role.setId(UUID.randomUUID().toString());
//2. 设置企业信息
role.setCompanyId(getCompanyId());
role.setCompanyName(getCompanyName());
roleService.save(role);
} else {
roleService.update(role);
}
//重定向到list方法
return "redirect:/system/role/list.do";
}
/**
* 跳转到修改
*/
@RequestMapping(value = "/toUpdate", name = "跳转角色编辑页面")
public String toUpdate(String id) {
//1. 根据id查询当前角色信息
Role role = roleService.findById(id);
request.setAttribute("role", role);
//2. 查询所有角色
List<Role> roleList = roleService.findAll(getCompanyId());
request.setAttribute("roleList", roleList);
//3. 转发到修改页面
return "/system/role/role-update";
}
/**
* 删除功能
*/
@RequestMapping(value = "/delete", name = "角色删除")
public String delete(String id) {
//调用service删除
roleService.delete(id);
//重定向到list方法
return "redirect:/system/role/list.do";
}
}