员工管理系统

该项目实现了以下功能,对应的源码与数据库文件在资源中可下载

项目部分展示

1. 数据库设计

创建数据库 employee,创建两个表 employee(员工表)和depart(部门表)

2. 后端部分

2.1 创建SpringBoot项目,导入依赖

<!--数据库连接-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybaits-plus-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.2</version>
</dependency>
<!--lombok-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
<!--thymeleaf模板引擎-->
<dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-java8time</artifactId>
</dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId>
</dependency>
<!--web-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.2 配置文件

spring:messages:basename: i18n.login  # 国际化配置datasource:             # 数据源配置driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/employee?serverTimezone=GMT%2b8&useSSL=true&useUnicode=true&characterEncoding=utf-8username: rootpassword: rootmybatis-plus:   # mybatis-plus配置configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志输出mapper-locations: classpath:mapper/*.xml  # xml文件的位置配置type-aliases-package: com.hua.pojo        # 别名

2.3 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {@TableId(type = IdType.AUTO)               // 自增  数据库该字段也要设计自增private Integer id;       // 员工编号private String name;      // 员工姓名private String password;  // 账号密码private Integer age;      // 员工年龄private Integer sex;      // 员工性别  1 男 0 女private String phone;     // 联系方式private Date birth;       // 员工生日@TableField(fill = FieldFill.INSERT)        // 此字段添加操作时自动填充private Date createtime;  // 创建时间@TableField(fill = FieldFill.INSERT_UPDATE) // 此字段添加、更新操作时自动填充private Date updatetime;  // 修改时间@Versionprivate Integer version;  // 乐观锁@TableLogicprivate Integer deleted;  // 逻辑删除private Integer departid; // 员工部门编号@TableField(updateStrategy = FieldStrategy.NEVER)  // 此字段不更新private Depart depart;    // 员工部门
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Depart {@TableId(type = IdType.AUTO)private Integer id;private String name;@TableField(fill = FieldFill.INSERT)private Date createtime;  // 创建时间@TableField(fill = FieldFill.INSERT_UPDATE)private Date updatetime;  // 修改时间@Versionprivate Integer version;  // 乐观锁@TableLogicprivate Integer deleted;  // 逻辑删除
}

2.4 自己的编写的配置

import java.util.Date;
// 自动填充配置
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("createtime",new Date(),metaObject); // 添加时填充createtime字段为当前的时间this.setFieldValByName("updatetime",new Date(),metaObject); // 添加时填充updatetime字段为当前的时间}@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updatetime",new Date(),metaObject); // 更新时填充updatetime字段为当前的时间}
}
// mybatis-plus的相关配置
@Configuration
public class MyBatisConfig {@Bean // 配置乐观锁OptimisticLockerInterceptor optimisticLockerInterceptor(){return new OptimisticLockerInterceptor();}@Bean // 配置逻辑删除ISqlInjector iSqlInjector(){return new LogicSqlInjector();}
}

2.5 dao层

@Repository
@Mapper  // 配置扫描该包
public interface DepartDao extends BaseMapper<Depart> {  // 继承BaseMapper 获取基本的CRUD操作}
@Repository
@Mapper    // 配置扫描该包
public interface EmployeeDao extends BaseMapper<Employee>{ // 继承BaseMapper 获取基本的CRUD方法// 查询所有员工List<Employee> getEmpList();   // 扩展自己的CRUD方法// 根据姓名查询员工Employee getEmployeeByName(@Param("name") String name);// 根据id查询员工Employee getEmployeeByID(@Param("id") int id);
}

EmployeeDao对应的xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hua.dao.EmployeeDao"><resultMap id="employeedepart" type="employee"><result property="id" column="id"></result><result property="name" column="name"></result><result property="password" column="password"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="phone" column="phone"></result><result property="birth" column="birth"></result><result property="createtime" column="createtime"></result><result property="updatetime" column="updatetime"></result><result property="version" column="version"></result><result property="deleted" column="deleted"></result><result property="departid" column="departid"></result><association property="depart" javaType="depart"><result property="id" column="did"></result><result property="name" column="dname"></result><result property="createtime" column="dcreatetime"></result><result property="updatetime" column="dupdatetime"></result><result property="version" column="dversion"></result><result property="deleted" column="ddeleted"></result></association></resultMap><select id="getEmpList" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid</select><select id="getEmployeeByName" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.name = #{name}</select><select id="getEmployeeByID" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.id = #{id}</select><select id="login" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.name = #{username} and e.password = #{password}</select>
</mapper>

2.6 service层

public interface DepartService {// 通过id获取部门信息Depart getDepartByID(int id);// 获取所有的部门信息List<Depart> getDepartList();// 通过id删除部门int delete(int id);// 通过id更新部门int update(Depart depart);// 增加部门int add(Depart depart);
}

DepartService对应的实现类

@Service
public class DepartServiceImpl implements DepartService{@AutowiredDepartDao departDao;  // 调用dao层/*** selectById()、selectList()、deleteById()、updateById()、insert()* 这些都是继承BaseMapper之后 就直接可以使用的* */@Overridepublic Depart getDepartByID(int id) {return departDao.selectById(id);}@Overridepublic List<Depart> getDepartList() {return departDao.selectList(null);}@Overridepublic int delete(int id) {return departDao.deleteById(id);}@Overridepublic int update(Depart depart) { // 需要用到乐观锁,需要先获取depart对象,再对其进行修改Depart departByID = this.getDepartByID(depart.getId()); departByID.setName(depart.getName());return departDao.updateById(departByID);}@Overridepublic int add(Depart depart) {return departDao.insert(depart);}
}
public interface EmployeeService {// 增加员工int add(Employee employee);// 查询所有员工List<Employee> getEmployeeList();// 根据id查询员工Employee getEmployeeByID(int id);// 根据姓名查询员工Employee getEmployeeByName(String name);// 根据id删除员工int delete(int id);// 根据id更新员工int update(Employee employee);
}

EmployeeService对应的实现类

@Service
public class EmployeeServiceImpl implements EmployeeService{@AutowiredEmployeeDao employeeDao; // 调用dao层@Overridepublic int add(Employee employee) {return employeeDao.insert(employee);}@Overridepublic List<Employee> getEmployeeList() {return employeeDao.getEmpList(); // 调用自己的方法}@Overridepublic Employee getEmployeeByID(int id) {return employeeDao.getEmployeeByID(id);// 调用自己的方法}@Overridepublic Employee getEmployeeByName(String name) {return employeeDao.getEmployeeByName(name);} // 调用自己的方法@Overridepublic int delete(int id) {return employeeDao.deleteById(id);}@Overridepublic int update(Employee employee) {Employee employeeByID = employeeDao.getEmployeeByID(employee.getId());employeeByID.setName(employee.getName());employeeByID.setPassword(employee.getPassword());employeeByID.setAge(employee.getAge());employeeByID.setSex(employee.getSex());employeeByID.setPhone(employee.getPhone());employeeByID.setBirth(employee.getBirth());employeeByID.setDepartid(employee.getDepartid());/*** 注意此处的employee属性的部门对象在数据库中并没有存储,所以不需要进行更新,* 只更新其另加的部门id字段即可,但是mybatis-plus默认的更新策略时更新所有不为空的字段,* 在更新的时候sql语句中会有部门对象的字段,此时就需要修改employee实体类的该字段的* 更新策略,改为never,这样sql语句中就不会再出现该字段* *///return employeeDao.updateById(employeeByID);}
}

3. 登录页面国际化

创建自己的国际化解析器

// 国际化的解析器
public class MyLocaleResolver implements LocaleResolver {@Overridepublic Locale resolveLocale(HttpServletRequest request) {String language = request.getParameter("language");Locale locale = Locale.getDefault(); // 如果language为空就是使用默认的if(!StringUtils.isEmpty(language)){String[] s = language.split("_");locale = new Locale(s[0],s[1]);}return locale;}@Overridepublic void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {}
}

将自己的解析器注册

@Configuration
// 自己的mvc配置
public class MyMVCConfig implements WebMvcConfigurer {@Override // 配置路由public void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("index");registry.addViewController("/index.html").setViewName("index");registry.addViewController("/main.html").setViewName("dashboard");}// 注册解析器@BeanLocaleResolver localeResolver(){return new MyLocaleResolver();}
}

修改首页,相应的提示文字要修改

4. 登录功能

dao层

Employee login(@Param("username") String username,@Param("password") String password);

xml

<select id="login" resultMap="employeedepart">select e.*,d.id as did,d.name as dnamefrom depart d,employee ewhere d.id = e.departid and e.name = #{username} and e.password = #{password}
</select>

service层

// 姓名和密码进行登录
Employee login(String username,String password);

实现类

@Override
public Employee login(String username, String password) {return employeeDao.login(username,password);
}

前端页面

<body class="text-center"><form class="form-signin" th:action="@{/login}"><img class="mb-4" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72"><h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}"></h1><h4 style="color: red" th:text="${msg}"></h4><label class="sr-only">Username</label><input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus=""><br/><label class="sr-only">Password</label><input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required=""><div class="checkbox mb-3"><label><input type="checkbox" value="remember-me"> [[#{login.remember}]]</label></div><button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button><p class="mt-5 mb-3 text-muted">© 2017-2018</p><a class="btn btn-sm" th:href="@{/index.html(language='zh_CN')}">中文</a><a class="btn btn-sm" th:href="@{/index.html(language='en_US')}">English</a></form>
</body>

controller

@RequestMapping("/login")
public String login(String username, String password, Model model, HttpSession session){Employee employee = employeeService.login(username, password);if (!StringUtils.isEmpty(employee)){session.setAttribute("employee",employee);return "redirect:/main.html"; // 重定向到首页}else {model.addAttribute("msg","用户名或者密码不正确");return "index";}
}

登录拦截器

public class LoginHandlerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();Object employee = session.getAttribute("employee");if(employee == null){ // 未登录,跳转到登录页,提示以下信息request.setAttribute("msg","无法访问,请先登录...");request.getRequestDispatcher("/index.html").forward(request,response);return false; // 进行拦截}else {return true;  // 放行}}
}

将拦截器注册到容器

@Configuration
// 自己的mvc配置
public class MyMVCConfig implements WebMvcConfigurer {@Override // 配置路由public void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("index");registry.addViewController("/index.html").setViewName("index");registry.addViewController("/main.html").setViewName("dashboard");}// 注册解析器@BeanLocaleResolver localeResolver(){return new MyLocaleResolver();}// 拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")  // 拦截所有请求.excludePathPatterns("/index.html","/","/login","/css/**","/js/**","/img/**"); // 对这些请求放行}
}

5. 注销功能

// controller层
@RequestMapping("/logout")
public String logout(HttpSession session){Object employee = session.getAttribute("employee");if(employee==null)  // 未登录 直接跳转登录页return "index";}else {session.removeAttribute("employee"); // 已登录 清除session 跳转登录页return "index";}
}

6. 公共页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" th:href="@{/asserts/icon/iconfont.css}">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="navbar"><a class="navbar-brand col-sm-3 col-md-2 mr-0" th:href="@{/main.html}">欢迎您 [[${session.employee.name}]]</a><input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"><ul class="navbar-nav px-3"><li class="nav-item text-nowrap"><a class="nav-link" th:href="@{/logout}">退出登录</a></li></ul>
</nav><nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar"><div class="sidebar-sticky"><ul class="nav flex-column"><li class="nav-item"><a class="nav-link active" th:href="@{/main.html}">首页</a></li><li class="nav-item"><a class="nav-link" href="#">xxxxx</a></li><li class="nav-item"><a class="nav-link" href="#">部门管理</a></li><li class="nav-item"><a class="nav-link" th:href="@{/emp/list}">员工管理</a></li><li class="nav-item"><a class="nav-link" href="#">xxxxx</a></li><li class="nav-item"><a class="nav-link" href="#">xxxxx</a></li></ul></div>
</nav>
</body>
</html>

7. 员工展示页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>员工列表</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet"><style>tr{/*表格内容居中显示*/text-align: center;}</style>
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2>员工列表</h2><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>工号</th><th>姓名</th><th>年龄</th><th>性别</th><th>联系方式</th><th>生日</th><th>部门</th><th>创建日期</th><th>修改日期</th><th>操作</th></tr></thead><tbody><!--循环遍历后端传来的列表--><tr th:each="employee:${employeeList}"><td th:text="${employee.id}"></td><td th:text="${employee.name}"></td><td th:text="${employee.age}"></td><td th:text="${employee.sex==0?'女':'男'}"></td><td th:text="${employee.phone}"></td><!--格式化日期输出--><td th:text="${#dates.format(employee.birth,'yyyy-MM-dd')}"></td><td th:text="${employee.depart.name}"></td><td th:text="${#dates.format(employee.createtime,'yyyy-MM-dd HH:mm:ss')}"></td><td th:text="${#dates.format(employee.updatetime,'yyyy-MM-dd HH:mm:ss')}"></td><td><a class="btn btn-sm btn-primary" th:href="@{#}">修改</a><a class="btn btn-sm btn-danger"  th:href="@{#}">删除</a></td></tr></tbody></table></div></main></div>
</div>
</body>
</html>

controller

@RequestMapping("/emp/list")
public String list(Model model){List<Employee> employeeList = employeeService.getEmployeeList();model.addAttribute("employeeList",employeeList);return "list";
}

8. 添加员工

<!--在列表界面添加按钮-->
<h3><a class="btn  btn-success" style="float: right" th:href="@{/emp/toAdd}">添加员工</a></h3>

跳转添加页面

@RequestMapping("/emp/toAdd")
public String toAdd(Model model){List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList);return "emp/add";
}

添加页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加员工</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/emp/add}" method="post"><div class="form-group"><label>姓名</label><input type="text" name="name" class="form-control"></div><div class="form-group"><label>密码</label><input type="password" name="password" class="form-control"></div><div class="form-group"><label>年龄</label><input type="text" name="age" class="form-control"></div><div class="form-group"><label>性别</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="1"><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="0"><label class="form-check-label">女</label></div></div><div class="form-group"><label>联系方式</label><input type="text" name="phone" class="form-control"></div><div class="form-group"><label>生日</label>   <!--注意此处的日期格式  SpringBoot默认格式为 1778/12/12 12:12:12 可以在配置文件修改--><input type="text" class="form-control" placeholder="例如:1778-12-12" name="birth"></div><div class="form-group"><label>部门</label><!--注意这边应该不是department--><select class="form-control" name="departid"><option th:each="department:${departList}" th:value="${department.id}">[[${department.name}]]</option></select></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
</body>
</html>

配置文件

spring:messages:basename: i18n.login  # 国际化配置datasource:             # 数据源配置driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/employee?serverTimezone=GMT%2b8&useSSL=true&useUnicode=true&characterEncoding=utf-8username: rootpassword: rootthymeleaf: cache: false  # 关闭thymeleaf的缓存mvc:format:date: yyyy-MM-dd HH:mm:ss # 修改默认日期格式
mybatis-plus:   # mybatis-plus配置configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志输出mapper-locations: classpath:mapper/*.xml  # xml文件的位置配置type-aliases-package: com.hua.pojo        # 别名

添加

@RequestMapping("/emp/add")
public String add(Employee employee){employeeService.add(employee);return "redirect:/emp/list";
}

9. 修改员工

<a class="btn btn-sm btn-primary" th:href="@{/emp/toUpdate/}+${employee.id}">修改</a>

跳转修改页面

@RequestMapping("/emp/toUpdate/{id}")
public String toUpdate(@PathVariable("id") int id,Model model){ // 需要将指定id的员工信息和部门列表返回Employee employeeByID = employeeService.getEmployeeByID(id);model.addAttribute("employee",employeeByID);List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList);return "emp/update";
}

修改页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加员工</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/emp/update}" method="post"><input type="hidden" name="id" th:value="${employee.id}"><div class="form-group"><label>姓名</label><input type="text" name="name" th:value="${employee.name}"  class="form-control"></div><div class="form-group"><label>密码</label><input type="text" name="password" th:value="${employee.password}" class="form-control"></div><div class="form-group"><label>年龄</label><input type="text" name="age" th:value="${employee.age}" class="form-control"></div><div class="form-group"><label>性别</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="1" th:checked="${employee.sex==1}"><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="0" th:checked="${employee.sex==0}"><label class="form-check-label">女</label></div></div><div class="form-group"><label>联系方式</label><input type="text" name="phone" th:value="${employee.phone}" class="form-control"></div><div class="form-group"><label>生日</label><!--注意此处的日期格式  SpringBoot默认格式为 1778/12/12 12:12:12 可以在配置文件修改--><input type="text" class="form-control" th:value="${employee.birth.toLocaleString()}" placeholder="例如:1778-12-12" name="birth"></div><div class="form-group"><label>部门</label><select class="form-control" name="departid"><option th:each="department:${departList}" th:value="${department.id}" th:selected="${employee.departid==department.id}">[[${department.name}]]</option></select></div><button type="submit" class="btn btn-primary">修改</button></form></main></div>
</div>
</body>
</html>

修改操作

@RequestMapping("/emp/update")
public String update(Employee employee){System.out.println(employee);employeeService.update(employee);return "redirect:/emp/list";
}

10. 删除员工

<a class="btn btn-sm btn-danger"  th:href="@{/emp/delete/}+${employee.id}">删除</a>

删除操作

@RequestMapping("/emp/delete/{id}")
public String delete(@PathVariable("id") int id){employeeService.delete(id);return "redirect:/emp/list";
}

此时出现一个问题,发现数据库中已经删除,但是列表中还会查到员工,原因是用到了逻辑删除,而sql语句不是使用mybatis-plus原生的语句,是自己编写的,所以where条件中需要添加 deleted = 0

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hua.dao.EmployeeDao"><resultMap id="employeedepart" type="employee"><result property="id" column="id"></result><result property="name" column="name"></result><result property="password" column="password"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="phone" column="phone"></result><result property="birth" column="birth"></result><result property="createtime" column="createtime"></result><result property="updatetime" column="updatetime"></result><result property="version" column="version"></result><result property="deleted" column="deleted"></result><result property="departid" column="departid"></result><association property="depart" javaType="depart"><result property="id" column="did"></result><result property="name" column="dname"></result><result property="createtime" column="dcreatetime"></result><result property="updatetime" column="dupdatetime"></result><result property="version" column="dversion"></result><result property="deleted" column="ddeleted"></result></association></resultMap><select id="getEmpList" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.deleted = 0</select><select id="getEmployeeByName" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.name = #{name} and e.deleted = 0</select><select id="getEmployeeByID" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.id = #{id} and e.deleted = 0</select><select id="login" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee ewhere d.id = e.departid and e.name = #{username} and e.password = #{password} and e.deleted = 0</select>
</mapper>

11. 查询员工

通过名字模糊查询 或者 通过部门名字查询

dao层

// 用户名或部门查询
List<Employee> get(@Param("name") String name,@Param("departid") int departid);

xml文件

<select id="get" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeletedfrom depart d,employee e<where>   <!--此处用到了mybatis的模糊查询-->d.id = e.departid and e.deleted = 0<if test="name!=null">  <!--如果name不为空,就加上下边一条查询语句-->and e.name like "%"#{name}"%"</if><if test="departid!=0"> <!--如果departid不为0,就加上下边一条查询语句-->and e.departid = #{departid}</if></where>
</select>

service层

// 名字或部门进行查询
List<Employee> get(String name,int id);

service实现类

@Override
public List<Employee> get(String name, int id) {if (StringUtils.isEmpty(name)){  // 此处需要判断一下,因为传来的值,可能为null也可能为"",而sql语句只判断了空值,所以将两种可能全部赋值为nullname=null;}return employeeDao.get(name,id);
}

前端页面

<form class="form-inline" role="form" th:action="@{/emp/get}"><div class="form-group col-lg-3">员工姓名:<input type="text" name="name" class="form-control" placeholder="请输入员工姓名"></div><div class="form-group col-lg-3">部门:<select name="departid"><option value="0">---请选择---</option><option th:each="depart:${departList}" th:value="${depart.id}" th:text="${depart.name}"></option></select></div><div class="form-group col-lg-3" ><input type="submit" value="查询"></div>
</form>

controller

@RequestMapping("/emp/list")
public String list(Model model){List<Employee> employeeList = employeeService.getEmployeeList();System.out.println(employeeList);model.addAttribute("employeeList",employeeList);List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList);  // 需要修改之前进行员工列表界面所携带的参数,将部门列表加上return "emp/list";
}
@RequestMapping("/emp/get")
public String get(String name,String departid,Model model){List<Employee> employeeList = employeeService.get(name, Integer.parseInt(departid));model.addAttribute("employeeList",employeeList);List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList); // 需要注意的是   此处仍需要传部门列表return "emp/list";
}

12. 部门的CRUD与员工的类似,相对简单 直接上代码

12.1 后端代码

dao层

@Repository
@Mapper  // 配置扫描该包
public interface DepartDao extends BaseMapper<Depart> {  // 继承BaseMapper 获取基本的CRUD操作}

没有附加自己的sql语句,所以没有.xml文件

service层

public interface DepartService {// 通过id获取部门信息Depart getDepartByID(int id);// 获取所有的部门信息List<Depart> getDepartList();// 通过id删除部门int delete(int id);// 通过id更新部门int update(Depart depart);// 增加部门int add(Depart depart);
}

实现类

@Service
public class DepartServiceImpl implements DepartService{@AutowiredDepartDao departDao;  // 调用dao层/*** selectById()、selectList()、deleteById()、updateById()、insert()* 这些都是继承BaseMapper之后 就直接可以使用的* */@Overridepublic Depart getDepartByID(int id) {return departDao.selectById(id);}@Overridepublic List<Depart> getDepartList() {return departDao.selectList(null);}@Overridepublic int delete(int id) {return departDao.deleteById(id);}@Overridepublic int update(Depart depart) { // 需要用到逻辑删除,需要先获取depart对象,再对其进行修改Depart departByID = this.getDepartByID(depart.getId());departByID.setName(depart.getName());return departDao.updateById(departByID);}@Overridepublic int add(Depart depart) {return departDao.insert(depart);}
}

12.2 部门展示

controller

@RequestMapping("/dep/list")
public String list(Model model){List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList); return "dep/list";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>员工列表</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet"><style>tr{/*表格内容居中显示*/text-align: center;}</style>
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2>部门列表</h2><h3><a class="btn  btn-success" style="float: right" th:href="@{/dep/toAdd}">添加部门</a></h3><br/><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>部门编号</th><th>部门名称</th><th>创建时间</th><th>修改时间</th><th>操作</th></tr></thead><tbody><!--循环遍历后端传来的列表--><tr th:each="depart:${departList}"><td th:text="${depart.id}"></td><td th:text="${depart.name}"></td><td th:text="${#dates.format(depart.createtime,'yyyy-MM-dd HH:mm:ss')}"></td><td th:text="${#dates.format(depart.updatetime,'yyyy-MM-dd HH:mm:ss')}"></td><td><a class="btn btn-sm btn-primary" th:href="@{/dep/toUpdate/}+${depart.id}">修改</a><a class="btn btn-sm btn-danger"  th:href="@{/dep/delete/}+${depart.id}">删除</a></td></tr></tbody></table></div></main></div>
</div>
</body>
</html>

12.3 增加部门

controller

@RequestMapping("/dep/toAdd")
public String toAdd(){return "dep/add";  // 跳转到增加页面
}
@RequestMapping("/dep/add")
public String add(Depart depart){departService.add(depart);  // 增加操作return "redirect:/dep/list";
}

前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加部门</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/dep/add}" method="post"><div class="form-group"><label>部门名称</label><input type="text" name="name" class="form-control"></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
</body>
</html>

12.4 修改部门

controller

@RequestMapping("/dep/toUpdate/{id}")  // 跳转到修改页面 需要携带该部门的信息
public String toUpdate(@PathVariable("id") int id,Model model){Depart departByID = departService.getDepartByID(id);model.addAttribute("depart",departByID);return "dep/update";
}
@RequestMapping("/dep/update")
public String update(Depart depart){departService.update(depart);  // 修改操作return "redirect:/dep/list";
}

前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加员工</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/dep/update}" method="post"><input type="hidden" name="id" th:value="${depart.id}"><div class="form-group"><label>部门名称</label><input type="text" name="name" th:value="${depart.name}"  class="form-control"></div><button type="submit" class="btn btn-primary">修改</button></form></main></div>
</div>
</body>
</html>

12.5 删除部门

controller

@RequestMapping("/dep/delete/{id}")
public String delete(@PathVariable("id") int id){departService.delete(id);return "redirect:/dep/list";
}
}

13. 角色管理

现在想要新增一个表,角色表,员工属性中也有对应的角色信息,另外使用shiro进行权限管理,对于员工的管理进行了修改。

添加依赖

<!--shiro与thymeleaf整合包-->
<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.1.0</version>
</dependency>
<!--shiro-->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.7.1</version>
</dependency>

13.1 数据库设计

员工表

角色表

13.2 后端

实体类

// 员工实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {@TableId(type = IdType.AUTO)private Integer id;       // 员工编号private String name;      // 员工姓名private String password;  // 账号密码private Integer age;      // 员工年龄private Integer sex;      // 员工性别  1 男 0 女private String phone;     // 联系方式private Date birth;       // 员工生日private Integer role;     // 角色编号@TableField(updateStrategy = FieldStrategy.NEVER)private Roles roles;      // 角色@TableField(fill = FieldFill.INSERT)private Date createtime;  // 创建时间@TableField(fill = FieldFill.INSERT_UPDATE)private Date updatetime;  // 修改时间@Versionprivate Integer version;  // 乐观锁@TableLogicprivate Integer deleted;  // 逻辑删除private Integer departid; // 员工部门编号@TableField(updateStrategy = FieldStrategy.NEVER)private Depart depart;    // 员工部门
}
// 角色实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Roles implements Serializable {@TableId(type = IdType.AUTO)  // id自增 数据库字段也需自增private Integer id;            private String name;          // 角色名称private String perms;         // 角色权限
}

dao层

// EmployeeDao
@Repository
@Mapper    // 配置扫描该包
public interface EmployeeDao extends BaseMapper<Employee>{ // 继承BaseMapper 获取基本的CRUD方法// 查询所有员工List<Employee> getEmpList();   // 扩展自己的CRUD方法// 根据姓名查询员工Employee getEmployeeByName(@Param("name") String name);// 根据id查询员工Employee getEmployeeByID(@Param("id") int id);// 用户名和密码进行登录Employee login(@Param("username") String username,@Param("password") String password);// 根据用户名或部门或角色查询  List<Employee> get(@Param("name") String name,@Param("departid") int departid,@Param("roleid") int roleid);// 根据姓名查询员工  之后设计员工登录的时候只显示自己的信息  List<Employee> getEmployee(@Param("name") String name);// 根据部门查询员工  之后设计各个部门经理登录会会显示各自部门的员工List<Employee> getEmployeeByDepartId(@Param("departid") int departid);
}

xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hua.dao.EmployeeDao"><resultMap id="employeedepart" type="employee"><result property="id" column="id"></result><result property="name" column="name"></result><result property="password" column="password"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="phone" column="phone"></result><result property="birth" column="birth"></result><result property="role" column="role"></result><result property="createtime" column="createtime"></result><result property="updatetime" column="updatetime"></result><result property="version" column="version"></result><result property="deleted" column="deleted"></result><result property="departid" column="departid"></result><association property="roles" javaType="roles"><result property="id" column="rid"></result><result property="name" column="rname"></result><result property="perms" column="perms"></result></association><association property="depart" javaType="depart"><result property="id" column="did"></result><result property="name" column="dname"></result><result property="createtime" column="dcreatetime"></result><result property="updatetime" column="dupdatetime"></result><result property="version" column="dversion"></result><result property="deleted" column="ddeleted"></result></association></resultMap><!--代码运行时要将该文件的注释删掉--><!--需要注意的是 自己写的sql语句 mybatis-plus查询的时候不会自动增加 deleted=0条件,需要自己添加--><select id="getEmpList" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.deleted = 0</select>  <select id="getEmployeeByName" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.name = #{name} and e.deleted = 0</select><select id="getEmployeeByID" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.id = #{id} and e.deleted = 0</select><select id="login" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.name = #{username} and e.password = #{password} and e.deleted = 0</select><!--该处用到了mybatis的动态sql,即查询时名字可能输入也可能不输入,部门和角色也有可能选择与不选择,都需要判断是否有值,只有在有值的时候才会加上相应的sql语句--><select id="get" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles r<where>d.id = e.departid and r.id = e.role and e.deleted = 0<if test="name!=null">and e.name like "%"#{name}"%"   <!--模糊查询--></if><if test="departid!=0">and e.departid = #{departid}</if><if test="roleid!=0">and e.role = #{roleid}</if></where></select><select id="getEmployee" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.name = #{name} and e.deleted = 0</select><select id="getEmployeeByDepartId" resultMap="employeedepart">select e.*,d.id as did,d.name as dname,d.createtime as dcreatetime,d.updatetime as dupdatetime,d.version as dversion,d.deleted as ddeleted,r.id as rid,r.name as rname,r.permsfrom depart d,employee e,roles rwhere d.id = e.departid and r.id = e.role and e.deleted = 0 and e.departid = #{departid}</select>
</mapper>
@Repository
@Mapper
public interface RoleDao extends BaseMapper<Roles> {  // 角色相关的CRUD使用mybatis-plus自带的语句
}

service层

public interface EmployeeService {// 增加员工int add(Employee employee);// 查询所有员工List<Employee> getEmployeeList();// 根据id查询员工Employee getEmployeeByID(int id);// 根据姓名查询员工Employee getEmployeeByName(String name);// 根据id删除员工int delete(int id);// 根据id更新员工int update(Employee employee);// 姓名和密码进行登录Employee login(String username,String password);// 名字或部门进行查询List<Employee> get(String name,int departid,int roleid);// 根据姓名查询员工List<Employee> getEmployee(String name);// 根据部门id查询员工List<Employee> getEmployeeByDepart(int departid);
}

实现类

@Service
public class EmployeeServiceImpl implements EmployeeService{@AutowiredEmployeeDao employeeDao; // 调用dao层@Overridepublic int add(Employee employee) {return employeeDao.insert(employee);}@Overridepublic List<Employee> getEmployeeList() {return employeeDao.getEmpList(); // 调用自己的方法}@Overridepublic Employee getEmployeeByID(int id) {return employeeDao.getEmployeeByID(id);// 调用自己的方法}@Overridepublic Employee getEmployeeByName(String name) {return employeeDao.getEmployeeByName(name);} // 调用自己的方法@Overridepublic int delete(int id) {return employeeDao.deleteById(id);}@Overridepublic int update(Employee employee) {Employee employeeByID = employeeDao.getEmployeeByID(employee.getId());employeeByID.setName(employee.getName());employeeByID.setPassword(employee.getPassword());employeeByID.setAge(employee.getAge());employeeByID.setSex(employee.getSex());employeeByID.setPhone(employee.getPhone());employeeByID.setBirth(employee.getBirth());employeeByID.setRole(employee.getRole());employeeByID.setDepartid(employee.getDepartid());/*** 注意此处的employee属性的部门对象在数据库中并没有存储,所以不需要进行更新,* 只更新其另加的部门id字段即可,但是mybatis-plus默认的更新策略时更新所有不为空的字段,* 在更新的时候sql语句中会有部门对象的字段,此时就需要修改employee实体类的该字段的* 更新策略,改为never,这样sql语句中就不会再出现该字段* *///return employeeDao.updateById(employeeByID);}@Overridepublic Employee login(String username, String password) {return employeeDao.login(username,password);}@Overridepublic List<Employee> get(String name, int departid,int roleid) {if (StringUtils.isEmpty(name)){ // 此处前端可能会传来null或者"",此处统一变为null,方便sql语句判断name=null;}return employeeDao.get(name,departid,roleid);}@Overridepublic List<Employee> getEmployee(String name) {return employeeDao.getEmployee(name);}@Overridepublic List<Employee> getEmployeeByDepart(int departid) {return employeeDao.getEmployeeByDepartId(departid);}
}
public interface RoleService {// 查询所有的角色List<Roles> getRolesList();// 增加角色int add(Roles roles);// 删除角色int delete(int id);// 更新角色int update(Roles roles);// 根据id查询角色Roles getRoleByID(int id);// 根据名字删除角色int deleteByName(String name);// 根据名字查询角色Roles getRoleByName(String name);
}

实现类

@Service
public class RoleServiceImpl implements RoleService{@AutowiredRoleDao roleDao;  // 调用dao层@Overridepublic List<Roles> getRolesList() {return roleDao.selectList(null);}@Overridepublic int add(Roles roles) {return roleDao.insert(roles);}@Overridepublic int delete(int id) {return roleDao.deleteById(id);}@Overridepublic int update(Roles roles) {return roleDao.updateById(roles);}@Overridepublic Roles getRoleByID(int id) {return roleDao.selectById(id);}@Overridepublic int deleteByName(String name) {QueryWrapper<Roles> rolesQueryWrapper = new QueryWrapper<>();rolesQueryWrapper.eq("name",name);  // 使用条件构造器return roleDao.delete(rolesQueryWrapper);}@Overridepublic Roles getRoleByName(String name) {QueryWrapper<Roles> rolesQueryWrapper = new QueryWrapper<>();rolesQueryWrapper.eq("name",name); // 使用条件构造器return roleDao.selectOne(rolesQueryWrapper);}
}

controller层

@Controller
public class EmployeeController {@AutowiredEmployeeService employeeService;@AutowiredDepartService departService;@AutowiredRoleService roleService;@RequestMapping("/toLogin")public String toLogin(){return "index";}@RequestMapping("/login")public String login(String username, String password,Model model, HttpSession session){Subject subject = SecurityUtils.getSubject();  // 使用shiro 实现安全管理, 获取当前的对象UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {subject.login(token);  // 登录return "redirect:/main.html"; // 重定向到首页}catch (UnknownAccountException e){ model.addAttribute("msg","没有该用户");return "index";}catch (IncorrectCredentialsException e){model.addAttribute("msg","密码错误");return "index";}}@RequestMapping("/logout")public String logout(HttpSession session){Object employee = session.getAttribute("employee");if(employee==null){ // 未登录 直接跳转登录页return "index";}else {session.removeAttribute("employee");  // 已登录 清除session 跳转登录页return "index";}}@RequestMapping("/emp/list")public String list(Model model,HttpSession session){Employee employee = (Employee)session.getAttribute("employee");Employee employeeByID = employeeService.getEmployeeByID(employee.getId()); // 根据id重新查一遍,以防信息不准确String name = employeeByID.getRoles().getName();  // 得到当前角色名字List<Employee> employeeList = null;if(name.equals("管理员")){employeeList = employeeService.getEmployeeList(); // 当前登录的是管理员,查询全部的员工}else if (name.equals("普通员工")){employeeList = employeeService.getEmployee(employeeByID.getName()); // 当前登录的是普通员工,只能查询自己的信息}else{employeeList = employeeService.getEmployeeByDepart(employee.getDepartid()); // 当前登录的是部门经理,查询自己部门的员工}model.addAttribute("employeeList",employeeList);  // 统一将查询的员工信息返回前端List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList);  // 将所有的部门信息返回前端List<Roles> rolesList = roleService.getRolesList();model.addAttribute("rolesList",rolesList);    // 将所有的角色信息返回前端return "emp/list";}@RequestMapping("/emp/toAdd")public String toAdd(Model model){List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList); // 将所有的部门信息返回前端List<Roles> rolesList = roleService.getRolesList();model.addAttribute("rolesList",rolesList);   // 将所有的角色信息返回前端return "emp/add";}@RequestMapping("/emp/add")public String add(Employee employee){employeeService.add(employee); // 添加员工操作return "redirect:/emp/list";}@RequestMapping("/emp/toUpdate/{id}")public String toUpdate(@PathVariable("id") int id,Model model){Employee employeeByID = employeeService.getEmployeeByID(id); // 更新员工先查到该员工,将信息返回更新页面model.addAttribute("employee",employeeByID);List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList);List<Roles> rolesList = roleService.getRolesList();model.addAttribute("rolesList",rolesList);return "emp/update";}@RequestMapping("/emp/update")public String update(Employee employee){employeeService.update(employee); // 更新员工操作return "redirect:/emp/list";}@RequestMapping("/emp/delete/{id}")public String delete(@PathVariable("id") int id){employeeService.delete(id);      // 删除员工操作return "redirect:/emp/list";}@RequestMapping("/emp/get")public String get(String name,String departid,String roleid,Model model){List<Employee> employeeList = employeeService.get(name, Integer.parseInt(departid),Integer.parseInt(roleid));model.addAttribute("employeeList",employeeList); List<Depart> departList = departService.getDepartList();model.addAttribute("departList",departList); // 需要注意的是   此处仍需要传部门列表和角色列表List<Roles> rolesList = roleService.getRolesList();model.addAttribute("rolesList",rolesList);return "emp/list";}@RequestMapping("/unauthorized")public String unauthorized(){return "unauthorized";}  // 此处需要设置一个未授权页面,之后当有没有权限的用户不合法访问页面时会跳转到该页面
}
@Controller
public class RoleController {@AutowiredRoleService roleService;@RequestMapping("/role/list")public String list(Model model){List<Roles> rolesList = roleService.getRolesList();if(rolesList!=null){for (Roles roles : rolesList) {StringBuilder builder = new StringBuilder();if(!StringUtils.isEmpty(roles.getPerms())){String[] split = roles.getPerms().split(",");for (String s : split) {if(s.equals("emp:*")){builder.append("操作员工的所有权限--"); // 将数据库中的权限取出来,换成文字展示}if(s.equals("dep:*")){builder.append("操作部门的所有权限--");}if(s.equals("role:*")){builder.append("操作角色的所有权限--");}if(s.equals("emp:list")){builder.append("查看员工列表--");}if(s.equals("emp:toAdd")){builder.append("跳转增加员工--");}if(s.equals("emp:add")){builder.append("增加员工--");}if(s.equals("emp:toUpdate")){builder.append("跳转修改员工--");}if(s.equals("emp:update")){builder.append("修改员工--");}if(s.equals("emp:delete")){builder.append("删除员工--");}if(s.equals("emp:get")){builder.append("查询员工--");}if(s.equals("dep:list")){builder.append("查看部门列表--");}if(s.equals("dep:toAdd")){builder.append("跳转增加部门--");}if(s.equals("dep:add")){builder.append("增加部门--");}if(s.equals("dep:toUpdate")){builder.append("跳转修改部门--");}if(s.equals("dep:update")){builder.append("修改部门--");}if(s.equals("dep:delete")){builder.append("删除部门--");}if(s.equals("role:list")){builder.append("查看角色列表--");}if(s.equals("role:toAdd")){builder.append("跳转增加角色--");}if(s.equals("role:add")){builder.append("增加角色--");}if(s.equals("role:toUpdate")){builder.append("跳转修改角色--");}if(s.equals("role:update")){builder.append("修改角色--");}if(s.equals("role:delete")){builder.append("删除角色--");}if(s.equals("无")){builder.append("无权限");}}roles.setPerms(builder.toString());}}}model.addAttribute("rolesList",rolesList);return "role/list";}@RequestMapping("/role/toAdd")public String toAdd(){return "role/add";}@RequestMapping("/role/add")public String add(Roles roles,String[] perms){if (roles.getName()==null || roles.getName()==""){  // 用户不输入,角色名字就是默认roles.setName("默认");}String perm = null;if(!StringUtils.isEmpty(perms)&&perms!=null){  List<String> list = Arrays.asList(perms); // 将用户在多选框中选择的权限组成一个list列表perm = String.join(",", list);  // 各个权限之间用,分割}else {perm = "无"; // 用户没有选择权限}roles.setPerms(perm);   // 设置权限roleService.add(roles); // 增加角色return "redirect:/role/list";}@RequestMapping("/role/toUpdate/{id}")public String toUpdate(@PathVariable("id") int id, Model model){Roles roleByID = roleService.getRoleByID(id);model.addAttribute("role",roleByID);
//        String perms = roleByID.getPerms();
//        String[] split = perms.split(",");
//        List<String> list = Arrays.asList(split);
//        System.out.println(list);
//        model.addAttribute("lists",list);return "role/update";}@RequestMapping("/role/update")public String update(Roles roles,String [] perms){if(roles.getName()==""||roles.getName()==null){roles.setName("默认");}String join = null;if(perms!=null&&!StringUtils.isEmpty(perms)){List<String> list = Arrays.asList(perms);join = String.join(",", list);}roles.setPerms(join);roleService.update(roles);return "redirect:/role/list";}@RequestMapping("/role/delete/{id}")public String delete(@PathVariable("id") int id){roleService.delete(id);return "redirect:/role/list";}
}

shiro安全

public class MyRealm extends AuthorizingRealm {@AutowiredEmployeeService employeeService;@Override // 授权// 通过验证后,会对登录的用户进行授权protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();Subject subject = SecurityUtils.getSubject();Employee employee = (Employee)subject.getPrincipal(); // 获取当前登录的用户String perms = employee.getRoles().getPerms();        // 将数据库中权限字段以,进行拆分String[] split = perms.split(",");                    // 构成权限数组List<String> list = Arrays.asList(split);info.addStringPermissions(list);                      // 授予权限return info;}@Override // 认证// 会从登录请求到此protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {UsernamePasswordToken token1 = (UsernamePasswordToken) token;String username = token1.getUsername();Employee employeeByName = employeeService.getEmployeeByName(username); // 拿到当前的登录的用户名if(employeeByName==null){ // 用户不存在,返回为空,此时登录请求会出现异常UnknownAccountException,提示前端用户名不存在return null;}Subject subject = SecurityUtils.getSubject();Session session = subject.getSession();session.setAttribute("employee",employeeByName); // 将当前的登录用户存入sessionreturn new SimpleAuthenticationInfo(employeeByName,employeeByName.getPassword(),""); // shiro会自己判断密码是否正确,不正确同样会出现异常,提示前端密码不正确}
}
@Configuration
public class ShiroConfig {// 3.ShiroFilterFactoryBean@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager manager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();// 关联DefaultWebSecurityManager,同样需要传参引入,此处的bean使用了别名bean.setSecurityManager(manager);Map<String,String> map = new LinkedHashMap<>();// 员工管理 所需权限map.put("/emp/list","perms[emp:list]");map.put("/emp/toAdd","perms[emp:toAdd]");map.put("/emp/add","perms[emp:add]");map.put("/emp/toUpdate/**","perms[emp:toUpdate]");map.put("/emp/update","perms[emp:update]");map.put("/emp/delete/**","perms[emp:delete]");map.put("/emp/get","perms[emp:get]");// 部门管理 所需权限map.put("/dep/list","perms[dep:list]");map.put("/dep/toAdd","perms[dep:toAdd]");map.put("/dep/add","perms[dep:add]");map.put("/dep/toUpdate/**","perms[dep:toUpdate]");map.put("/dep/update","perms[dep:update]");map.put("/dep/delete/**","perms[dep:delete]");// 角色管理 所需权限map.put("/role/list","perms[role:list]");map.put("/role/toAdd","perms[role:toAdd]");map.put("/role/add","perms[role:add]");map.put("/role/toUpdate/**","perms[role:toUpdate]");map.put("/role/update","perms[role:update]");map.put("/role/delete/**","perms[role:delete]");bean.setFilterChainDefinitionMap(map);    // 设置访问权限bean.setUnauthorizedUrl("/unauthorized"); // 设置未授权跳转页面return bean;}//2.DefaultWebSecurityManager@Bean(name = "manager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm)    {DefaultWebSecurityManager manager = new DefaultWebSecurityManager();// 关联Realm 因为MyRealm已经被Spring接管,所以需要传参引入,传参的时候需要用到Qualifier指定bean的名字manager.setRealm(myRealm);return manager;}//1.创建Realm@Beanpublic MyRealm myRealm(){return new MyRealm();}// shiro整合thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();}
}

13.3 前端

员工展示

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>员工列表</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet"><style>tr{/*表格内容居中显示*/text-align: center;}</style>
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2>员工列表</h2><br/>    <!--此处使用了shiro与thfmeleaf整合, shiro:hasPermission 登录的角色需要有指定权限,该组件才会显示--><form shiro:hasPermission="'emp:get'" class="form-inline" role="form" th:action="@{/emp/get}" method="post"><div class="form-group col-lg-3">员工姓名:<input type="text" name="name" class="form-control" placeholder="请输入员工姓名"></div><div class="form-group col-lg-3" shiro:hasPermission="'emp:*'">部门:<select name="departid"><option value="0">---请选择---</option><option th:each="depart:${departList}" th:value="${depart.id}" th:text="${depart.name}"></option></select></div><div class="form-group col-lg-3" shiro:hasPermission="'emp:*'">角色:<select name="roleid"><option value="0">---请选择---</option><option th:each="roles:${rolesList}" th:value="${roles.id}" th:text="${roles.name}"></option></select></div><div class="form-group col-lg-3" ><input type="submit" value="查询"></div></form><h3><a shiro:hasPermission="'emp:toAdd'" class="btn  btn-success" style="float: right" th:href="@{/emp/toAdd}">添加员工</a></h3><br/><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>工号</th><th>姓名</th><th>年龄</th><th>性别</th><th>联系方式</th><th>生日</th><th>角色</th><th>部门</th><th>创建日期</th><th>修改日期</th><th>操作</th></tr></thead><tbody><!--循环遍历后端传来的列表--><tr th:each="employee:${employeeList}"><td th:text="${employee.id}"></td><td th:text="${employee.name}"></td><td th:text="${employee.age}"></td><td th:text="${employee.sex==0?'女':'男'}"></td><td th:text="${employee.phone}"></td><!--格式化日期输出--><td th:text="${#dates.format(employee.birth,'yyyy-MM-dd')}"></td><td th:text="${employee.roles.name}"></td><td th:text="${employee.depart.name}"></td><td th:text="${#dates.format(employee.createtime,'yyyy-MM-dd HH:mm:ss')}"></td><td th:text="${#dates.format(employee.updatetime,'yyyy-MM-dd HH:mm:ss')}"></td><td><a shiro:hasPermission="'emp:toUpdate'" class="btn btn-sm btn-primary" th:href="@{/emp/toUpdate/}+${employee.id}">修改</a><a shiro:hasPermission="'emp:delete'" class="btn btn-sm btn-danger"  th:href="@{/emp/delete/}+${employee.id}">删除</a></td></tr></tbody></table></div></main></div>
</div>
</body>
</html>

添加员工

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加员工</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/emp/add}" method="post"><div class="form-group"><label>姓名</label><input type="text" name="name" class="form-control" required></div><div class="form-group"><label>密码</label><input type="password" name="password" class="form-control" required></div><div class="form-group"><label>年龄</label><input type="text" name="age" class="form-control" required></div><div class="form-group"><label>性别</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="1" required><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="0" required><label class="form-check-label">女</label></div></div><div class="form-group"><label>联系方式</label><input type="text" name="phone" class="form-control" required></div><div class="form-group"><label>生日</label><!--注意此处的日期格式  SpringBoot默认格式为 1778/12/12 12:12:12 可以在配置文件修改--><input type="text" class="form-control" placeholder="例如:1778-12-12" name="birth" required></div><div class="form-group"><label>部门</label><select class="form-control" name="departid" required><option th:each="department:${departList}" th:value="${department.id}">[[${department.name}]]</option></select></div><div class="form-group"><label>角色</label><select class="form-control" name="role" required><option th:each="roles:${rolesList}" th:value="${roles.id}">[[${roles.name}]]</option></select></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
</body>
</html>

修改员工

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>修改员工</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/emp/update}" method="post"><input type="hidden" name="id" th:value="${employee.id}"><div class="form-group"><label>姓名</label><input type="text" name="name" th:value="${employee.name}"  class="form-control"></div><div class="form-group"><label>密码</label><input type="text" name="password" th:value="${employee.password}" class="form-control"></div><div class="form-group"><label>年龄</label><input type="text" name="age" th:value="${employee.age}" class="form-control"></div><div class="form-group"><label>性别</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="1" th:checked="${employee.sex==1}"><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="sex" value="0" th:checked="${employee.sex==0}"><label class="form-check-label">女</label></div></div><div class="form-group"><label>联系方式</label><input type="text" name="phone" th:value="${employee.phone}" class="form-control"></div><div class="form-group"><label>生日</label><!--注意此处的日期格式  SpringBoot默认格式为 1778/12/12 12:12:12 可以在配置文件修改--><input type="text" class="form-control" th:value="${employee.birth.toLocaleString()}" placeholder="例如:1778-12-12" name="birth"></div><div class="form-group" shiro:hasPermission="'emp:*'"><label>部门</label><select class="form-control" name="departid"><option th:each="department:${departList}" th:value="${department.id}" th:selected="${employee.departid==department.id}">[[${department.name}]]</option></select></div><div class="form-group" shiro:hasPermission="'emp:*'"><label>角色</label><select class="form-control" name="role"><option th:each="roles:${rolesList}" th:value="${roles.id}" th:selected="${employee.role==roles.id}">[[${roles.name}]]</option></select></div><button type="submit" class="btn btn-primary">修改</button></form></main></div>
</div>
</body>
</html>

角色展示

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>角色列表</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet"><style>tr{/*表格内容居中显示*/text-align: center;}</style>
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2>角色列表</h2><h3><a shiro:hasPermission="'role:toAdd'" class="btn  btn-success" style="float: right" th:href="@{/role/toAdd}">添加角色</a></h3><br/><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>角色编号</th><th>角色名称</th><th>角色权限</th><th>操作</th></tr></thead><tbody><!--循环遍历后端传来的列表--><tr th:each="roles:${rolesList}"><td th:text="${roles.id}"></td><td th:text="${roles.name}"></td><td th:text="${roles.perms}"></td><td><a shiro:hasPermission="'role:toUpdate'" th:href="@{/role/toUpdate/}+${roles.id}" class="btn btn-sm btn-primary">修改</a><a shiro:hasPermission="'role:delete'" th:href="@{/role/delete/}+${roles.id}" class="btn btn-sm btn-danger">删除</a></td></tr></tbody></table></div></main></div>
</div>
</body>
</html>

角色添加

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>添加角色</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/role/add}" method="post"><div class="form-group"><label>角色名称</label><input type="text" name="name" class="form-control" placeholder="不填写会使用默认的..."></div><div class="form-group"><label>角色权限:</label><br/><br/><label>员工操作权限:</label><input type="checkbox" name="perms" value="emp:*">操作员工的所有权限--<input type="checkbox" name="perms" value="emp:list">查看员工列表--<input type="checkbox" name="perms" value="emp:toAdd">跳转添加员工--<input type="checkbox" name="perms" value="emp:add">添加员工--<input type="checkbox" name="perms" value="emp:toUpdate">跳转修改员工--<input type="checkbox" name="perms" value="emp:update">修改员工--<input type="checkbox" name="perms" value="emp:delete">删除员工--<input type="checkbox" name="perms" value="emp:get">查询员工--<br/><br/><br/><label>部门操作权限:</label><input type="checkbox" name="perms" value="dep:*">操作部门的所有权限--<input type="checkbox" name="perms" value="dep:list">查看部门列表--<input type="checkbox" name="perms" value="dep:toAdd">跳转添加部门--<input type="checkbox" name="perms" value="dep:add">添加部门--<input type="checkbox" name="perms" value="dep:toUpdate">跳转修改部门--<input type="checkbox" name="perms" value="dep:update">修改部门--<input type="checkbox" name="perms" value="dep:delete">删除部门--<br/><br/><br/><label>角色操作权限:</label><input type="checkbox" name="perms" value="role:*"/>操作角色的所有权限--<input type="checkbox" name="perms" value="role:list"/>查看角色列表--<input type="checkbox" name="perms" value="role:toAdd"/>跳转添加角色--<input type="checkbox" name="perms" value="role:add"/>添加角色--<input type="checkbox" name="perms" value="role:toUpdate"/>跳转修改角色--<input type="checkbox" name="perms" value="role:update"/>修改角色--<input type="checkbox" name="perms" value="role:delete"/>删除角色--</div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
</body>
</html>

更新角色

<!DOCTYPE html>
<html lang="en" xmlns:th="http://wwww.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content=""><meta name="author" content=""><title>修改角色</title><link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
</head><body>
<!--引入公共顶部栏-->
<div th:insert="~{commons/commons::navbar}"></div>
<div class="container-fluid"><div class="row"><!--引入公共侧边栏--><div th:insert="~{commons/commons::sidebar}"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/role/update}" method="post"><input type="hidden" name="id" th:value="${role.id}"><div class="form-group"><label>角色名称</label><input type="text" name="name" th:value="${role.name}"  class="form-control"></div><div class="form-group" ><label>角色权限:</label><br/><br/>
<!--此处曾想后端传来perms的列表,然后遍历, th:each="list:${lists}" th:checked="${list=='emp:*')}" 这样的话多选框会重复创建--><label>员工操作权限:</label><input type="checkbox" name="perms" value="emp:*"        th:checked="${#strings.containsIgnoreCase(role.perms,'emp:*')}">操作员工的所有权限--<input type="checkbox" name="perms" value="emp:list"     th:checked="${#strings.containsIgnoreCase(role.perms,'emp:list')}">查看员工列表--<input type="checkbox" name="perms" value="emp:toAdd"    th:checked="${#strings.containsIgnoreCase(role.perms,'emp:toAdd')}">跳转添加员工--<input type="checkbox" name="perms" value="emp:add"      th:checked="${#strings.containsIgnoreCase(role.perms,'emp:add')}">添加员工--<input type="checkbox" name="perms" value="emp:toUpdate" th:checked="${#strings.containsIgnoreCase(role.perms,'emp:toUpdate')}">跳转修改员工--<input type="checkbox" name="perms" value="emp:update"   th:checked="${#strings.containsIgnoreCase(role.perms,'emp:update')}">修改员工--<input type="checkbox" name="perms" value="emp:delete"   th:checked="${#strings.containsIgnoreCase(role.perms,'emp:delete')}">删除员工--<input type="checkbox" name="perms" value="emp:get"      th:checked="${#strings.containsIgnoreCase(role.perms,'emp:get')}">查询员工--<br/><br/><br/><label>部门操作权限:</label><input type="checkbox" name="perms" value="dep:*"        th:checked="${#strings.containsIgnoreCase(role.perms,'dep:*')}">操作部门的所有权限--<input type="checkbox" name="perms" value="dep:list"     th:checked="${#strings.containsIgnoreCase(role.perms,'dep:list')}">查看部门列表--<input type="checkbox" name="perms" value="dep:toAdd"    th:checked="${#strings.containsIgnoreCase(role.perms,'dep:toAdd')}">跳转添加部门--<input type="checkbox" name="perms" value="dep:add"      th:checked="${#strings.containsIgnoreCase(role.perms,'dep:add')}">添加部门--<input type="checkbox" name="perms" value="dep:toUpdate" th:checked="${#strings.containsIgnoreCase(role.perms,'dep:toUpdate')}">跳转修改部门--<input type="checkbox" name="perms" value="dep:update"   th:checked="${#strings.containsIgnoreCase(role.perms,'dep:update')}">修改部门--<input type="checkbox" name="perms" value="dep:delete"   th:checked="${#strings.containsIgnoreCase(role.perms,'dep:delete')}">删除部门--<br/><br/><br/><label>角色操作权限:</label><input type="checkbox" name="perms" value="role:*"       th:checked="${#strings.containsIgnoreCase(role.perms,'role:*')}">操作角色的所有权限--<input type="checkbox" name="perms" value="role:list"    th:checked="${#strings.containsIgnoreCase(role.perms,'role:list')}">查看角色列表--<input type="checkbox" name="perms" value="role:toAdd"   th:checked="${#strings.containsIgnoreCase(role.perms,'role:toAdd')}">跳转添加角色--<input type="checkbox" name="perms" value="role:add"     th:checked="${#strings.containsIgnoreCase(role.perms,'role:add')}">添加角色--<input type="checkbox" name="perms" value="role:toUpdate"th:checked="${#strings.containsIgnoreCase(role.perms,'role:toUpdate')}">跳转修改角色--<input type="checkbox" name="perms" value="role:update"  th:checked="${#strings.containsIgnoreCase(role.perms,'role:update')}">修改角色--<input type="checkbox" name="perms" value="role:delete"  th:checked="${#strings.containsIgnoreCase(role.perms,'role:delete')}">删除角色--</div><button type="submit" class="btn btn-primary">修改</button></form></main></div>
</div>
</body>
</html>

14. 总结

至此,这个简单的员工管理系统暂时告一段落,下面总结一下系统实现的功能:

收获:

  1. mybatis-plus。自动填充,乐观锁(先获取该对象,再对其更新),逻辑删除,自带的CRUD语句,

    多对一 ,自己编写查询sql时需要添加逻辑删除字段,动态sql,

@TableId(type = IdType.AUTO)  // 主键自增
@TableField(fill = FieldFill.INSERT_UPDATE)       // 增加和删除操作时自动填充,需要设置填充规则 MetaObjectHandler
@TableField(updateStrategy = FieldStrategy.NEVER) // 更新规则,更新操作时不更新该字段
@Version     // 乐观锁   OptimisticLockerInterceptor
@TableLogic  // 逻辑删除 ISqlInjector
  1. shiro使用。MyRealm(继承AuthorizingRealm重写授权和认证方法)、DefaultWebSecurityManager、ShiroFilterFactoryBean(设置访问具体页面需要那些权限),shiro整合thymeleaf。
  2. 国际化实现。编写properties文件,添加配置,页面中读取,编写解析器
  3. 登录拦截器。编写拦截规则,设置拦截与不拦截的请求。
  4. list操作。将数组转为list Arrays.asList(),在列表元素中间添加逗号,String.join(“,”, list);
  5. thymeleaf。#dates.format(time,‘yyyy-MM-dd HH:mm:ss’) 或 th:value=“${time.toLocaleString()}” 日期格式转换,#strings.containsIgnoreCase(role.perms,‘emp:*’) 某字符串包含某字符串,忽略大小写
  6. thymeleaf-shiro。shiro:hasPermission=" ‘user:add’ " 拥有某权限才显示

此项目是在学习完SpringBoot、mybatis-plus之后开始构建的,由于本人没有企业级项目开发经验,此项目纯属个人练习搭建,水平有限,其中有些逻辑肯定还不是很完善,还望各位批评指教。

SpringBoot项目实战:员工管理系统相关推荐

  1. springboot 项目实战 基本框架搭建(IDEA)

    springboot 项目实战 基本框架搭建(IDEA) IDEA下载 我使用的是破解的专业版IDEA,使用权一直到2089年: 下载IDEA: 下载processional版本,然后百度搜索激活码即 ...

  2. Vue整合SpringBoot项目实战之Vue+Element-Ui搭建前端项目

    Vue整合SpringBoot项目实战之Vue+Element-Ui搭建前端项目 源码(欢迎star): 前端项目代码 后端项目代码 系列文章: Vue整合SpringBoot项目实战之后端业务处理 ...

  3. 【SpringBoot项目实战】图片压缩包上传、解压、存储等等一套流程教学

    [SpringBoot项目实战]图片压缩包上传.解压.存储等等一套流程教学 前言 一.压缩包上传 1.接口实现 2.获取压缩包的文件名和文件路径 二.压缩包解压并保存 1.处理压缩包文件方法 解压缩步 ...

  4. Java项目实战---歌曲管理系统

    Java项目实战-歌曲管理系统 声明:本人仅整理了代码,方便大家进行调试优化,功能上还存在很多纰漏,欢迎大家评论区讨论 代码原地址放于文章末尾 一.实验目的: 掌握类的定义,JAVA应用程序的设计与实 ...

  5. Vue项目实战 —— 后台管理系统( pc端 ) 第三篇

    ​前期回顾    ​  Vue项目实战 -- 后台管理系统( pc端 ) 第二篇_0.活在风浪里的博客-CSDN博客前期回顾 Vue项目实战 -- 后台管理系统( pc端 ) 第一篇 _0.活在风浪里 ...

  6. Vue项目实战 —— 后台管理系统( pc端 ) 第一篇

    前期回顾     我只写注释 -- 让Ai写代码_0.活在风浪里的博客-CSDN博客前期回顾 Vue项目实战 -- 哔哩哔哩移动端开发-- 第二篇_0.活在风浪里的博客-CSDN博客https://b ...

  7. 【SpringBoot项目实战+思维导图】瑞吉外卖①(项目介绍、开发环境搭建、后台登陆/退出功能开发)

    文章目录 软件开发整体介绍 软件开发流程 角色分工 软件环境 瑞吉外卖项目介绍 项目介绍 产品原型 技术选型 功能架构 角色 开发环境搭建 数据库环境搭建 创建数据库 数据库表导入 数据库表介绍 Ma ...

  8. SSM项目实战:酒店管理系统

    使用的技术栈:Spring+SpringMVC+mybatis+Mysql+layui+Maven Maven 项目结构.项目配置项为: 服务器:apache-tomcat-9.0.0.M26 (必须 ...

  9. springboot项目实战_2019学习进阶之路:高并发+性能优化+Spring boot等大型项目实战...

    Java架构师主要需要做哪些工作呢? 负责设计和搭建软件系统架构(平台.数据库.接口和应用架构等),解决开发中各种系统架构问题. 优化现有系统的性能,解决软件系统平台关键技术问题攻关.核心功能模块设计 ...

最新文章

  1. Java判断文件类型
  2. SAP 既是供应商,又是客户-互清(清账 F110中使用)
  3. python可以在哪些平台安装_python都有哪些版本,如何在你的计算机上运行python?...
  4. android 上下扫描动画,Android扫描雷达动画
  5. Spring Boot配置文件加载顺序
  6. 查看数据库系统字符集
  7. linux更改桌面壁纸的脚本,自动更换桌面壁纸的脚本,支持Ubuntu 18.04系统
  8. python数据结构:进制转化探索
  9. 什么是oracle命名,ORACLE数据库命名规范
  10. SaltStack 第二板块安装说明 [2]
  11. k8s创建Deployment报错:missing required field “selector“ in io.k8s.api.apps.v1.DeploymentSpec
  12. 关于HTML+CSS3的一些笔记
  13. 用装饰器来进行登录验证
  14. jQuery基础(jQuery概念,jQuery与js入口函数的区别及其入口函数的其他写法和冲突问题)
  15. 网页上的html表格导出excel表格,网页表格导出至Excel
  16. 简谈PCB设计软件对比
  17. matlab 数据白化,数据白化
  18. matlab一维数组操作,Matlab创建一维数组的具体操作讲解
  19. 龙ol一键端服务器维护,龙OL一键端纯一键点两下OK问题及解答汇总贴.doc
  20. 阿里年薪50WJAVA工程师转大数据学习路线!

热门文章

  1. 【UE5 C++基础 05】UBT基础
  2. VR成为下一代计算平台的关键技术:面部追踪
  3. 见证国内人工智能与机器人技术的进步
  4. 基于SSH开发小型洗车门店客户管理系统
  5. Spring Cloud一些组件原理(一)
  6. 第一次视频面试给了小米前端
  7. [生而为人-思考] 沈定刚教授座谈会感悟记录
  8. Sql 中两个数除法计算结果等于0原因是什么?
  9. java实现幂等_接口幂等性如何实现?
  10. verilog编写数字频率计