员工管理系统
该项目实现了以下功能,对应的源码与数据库文件在资源中可下载
项目部分展示
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.Driver
url: jdbc:mysql://localhost:3306/employee?serverTimezone=GMT%2b8&useSSL=true&useUnicode=true&characterEncoding=utf-8
username: root
password: root
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 # 别名
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; // 修改时间
@Version
private Integer version; // 乐观锁
@TableLogic
private 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; // 修改时间
@Version
private Integer version; // 乐观锁
@TableLogic
private Integer deleted; // 逻辑删除
}
2.4 自己的编写的配置
import java.util.Date;
// 自动填充配置
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createtime",new Date(),metaObject); // 添加时填充createtime字段为当前的时间
this.setFieldValByName("updatetime",new Date(),metaObject); // 添加时填充updatetime字段为当前的时间
}
@Override
public 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 mapper
PUBLIC "-//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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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{
@Autowired
DepartDao departDao; // 调用dao层
/**
* selectById()、selectList()、deleteById()、updateById()、insert()
* 这些都是继承BaseMapper之后 就直接可以使用的
* */
@Override
public Depart getDepartByID(int id) {
return departDao.selectById(id);
}
@Override
public List<Depart> getDepartList() {
return departDao.selectList(null);
}
@Override
public int delete(int id) {
return departDao.deleteById(id);
}
@Override
public int update(Depart depart) { // 需要用到乐观锁,需要先获取depart对象,再对其进行修改
Depart departByID = this.getDepartByID(depart.getId());
departByID.setName(depart.getName());
return departDao.updateById(departByID);
}
@Override
public 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{
@Autowired
EmployeeDao employeeDao; // 调用dao层
@Override
public int add(Employee employee) {
return employeeDao.insert(employee);
}
@Override
public List<Employee> getEmployeeList() {
return employeeDao.getEmpList(); // 调用自己的方法
}
@Override
public Employee getEmployeeByID(int id) {
return employeeDao.getEmployeeByID(id);// 调用自己的方法
}
@Override
public Employee getEmployeeByName(String name) {
return employeeDao.getEmployeeByName(name);
} // 调用自己的方法
@Override
public int delete(int id) {
return employeeDao.deleteById(id);
}
@Override
public 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 {
@Override
public 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;
}
@Override
public 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");
}
// 注册解析器
@Bean
LocaleResolver 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 dname
from depart d,employee e
where 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 {
@Override
public 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");
}
// 注册解析器
@Bean
LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
// 拦截器
@Override
public 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.Driver
url: jdbc:mysql://localhost:3306/employee?serverTimezone=GMT%2b8&useSSL=true&useUnicode=true&characterEncoding=utf-8
username: root
password: root
thymeleaf:
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 mapper
PUBLIC "-//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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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 ddeleted
from depart d,employee e
where 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 ddeleted
from 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语句只判断了空值,所以将两种可能全部赋值为null
name=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{
@Autowired
DepartDao departDao; // 调用dao层
/**
* selectById()、selectList()、deleteById()、updateById()、insert()
* 这些都是继承BaseMapper之后 就直接可以使用的
* */
@Override
public Depart getDepartByID(int id) {
return departDao.selectById(id);
}
@Override
public List<Depart> getDepartList() {
return departDao.selectList(null);
}
@Override
public int delete(int id) {
return departDao.deleteById(id);
}
@Override
public int update(Depart depart) { // 需要用到逻辑删除,需要先获取depart对象,再对其进行修改
Depart departByID = this.getDepartByID(depart.getId());
departByID.setName(depart.getName());
return departDao.updateById(departByID);
}
@Override
public 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; // 修改时间
@Version
private Integer version; // 乐观锁
@TableLogic
private 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 mapper
PUBLIC "-//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.perms
from depart d,employee e,roles r
where 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.perms
from depart d,employee e,roles r
where 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.perms
from depart d,employee e,roles r
where 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.perms
from depart d,employee e,roles r
where 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.perms
from 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.perms
from depart d,employee e,roles r
where 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.perms
from depart d,employee e,roles r
where 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{
@Autowired
EmployeeDao employeeDao; // 调用dao层
@Override
public int add(Employee employee) {
return employeeDao.insert(employee);
}
@Override
public List<Employee> getEmployeeList() {
return employeeDao.getEmpList(); // 调用自己的方法
}
@Override
public Employee getEmployeeByID(int id) {
return employeeDao.getEmployeeByID(id);// 调用自己的方法
}
@Override
public Employee getEmployeeByName(String name) {
return employeeDao.getEmployeeByName(name);
} // 调用自己的方法
@Override
public int delete(int id) {
return employeeDao.deleteById(id);
}
@Override
public 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);
}
@Override
public Employee login(String username, String password) {
return employeeDao.login(username,password);
}
@Override
public List<Employee> get(String name, int departid,int roleid) {
if (StringUtils.isEmpty(name)){ // 此处前端可能会传来null或者"",此处统一变为null,方便sql语句判断
name=null;
}
return employeeDao.get(name,departid,roleid);
}
@Override
public List<Employee> getEmployee(String name) {
return employeeDao.getEmployee(name);
}
@Override
public 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{
@Autowired
RoleDao roleDao; // 调用dao层
@Override
public List<Roles> getRolesList() {
return roleDao.selectList(null);
}
@Override
public int add(Roles roles) {
return roleDao.insert(roles);
}
@Override
public int delete(int id) {
return roleDao.deleteById(id);
}
@Override
public int update(Roles roles) {
return roleDao.updateById(roles);
}
@Override
public Roles getRoleByID(int id) {
return roleDao.selectById(id);
}
@Override
public int deleteByName(String name) {
QueryWrapper<Roles> rolesQueryWrapper = new QueryWrapper<>();
rolesQueryWrapper.eq("name",name); // 使用条件构造器
return roleDao.delete(rolesQueryWrapper);
}
@Override
public Roles getRoleByName(String name) {
QueryWrapper<Roles> rolesQueryWrapper = new QueryWrapper<>();
rolesQueryWrapper.eq("name",name); // 使用条件构造器
return roleDao.selectOne(rolesQueryWrapper);
}
}
controller层
@Controller
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@Autowired
DepartService departService;
@Autowired
RoleService 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 {
@Autowired
RoleService 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 {
@Autowired
EmployeeService 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); // 将当前的登录用户存入session
return new SimpleAuthenticationInfo(employeeByName,employeeByName.getPassword(),""); // shiro会自己判断密码是否正确,不正确同样会出现异常,提示前端密码不正确
}
}
@Configuration
public class ShiroConfig {
// 3.ShiroFilterFactoryBean
@Bean
public 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
@Bean
public MyRealm myRealm(){
return new MyRealm();
}
// shiro整合thymeleaf
@Bean
public 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. 总结
至此,这个简单的员工管理系统暂时告一段落,下面总结一下系统实现的功能:
收获:
-
mybatis-plus。自动填充,乐观锁(先获取该对象,再对其更新),逻辑删除,自带的CRUD语句,
多对一 ,自己编写查询sql时需要添加逻辑删除字段,动态sql,
@TableId(type = IdType.AUTO) // 主键自增
@TableField(fill = FieldFill.INSERT_UPDATE) // 增加和删除操作时自动填充,需要设置填充规则 MetaObjectHandler
@TableField(updateStrategy = FieldStrategy.NEVER) // 更新规则,更新操作时不更新该字段
@Version // 乐观锁 OptimisticLockerInterceptor
@TableLogic // 逻辑删除 ISqlInjector
- shiro使用。MyRealm(继承AuthorizingRealm重写授权和认证方法)、DefaultWebSecurityManager、ShiroFilterFactoryBean(设置访问具体页面需要那些权限),shiro整合thymeleaf。
- 国际化实现。编写properties文件,添加配置,页面中读取,编写解析器
- 登录拦截器。编写拦截规则,设置拦截与不拦截的请求。
- list操作。将数组转为list Arrays.asList(),在列表元素中间添加逗号,String.join(“,”, list);
- thymeleaf。#dates.format(time,‘yyyy-MM-dd HH:mm:ss’) 或 th:value=“${time.toLocaleString()}” 日期格式转换,#strings.containsIgnoreCase(role.perms,‘emp:*’) 某字符串包含某字符串,忽略大小写
- thymeleaf-shiro。shiro:hasPermission=" ‘user:add’ " 拥有某权限才显示
此项目是在学习完SpringBoot、mybatis-plus之后开始构建的,由于本人没有企业级项目开发经验,此项目纯属个人练习搭建,水平有限,其中有些逻辑肯定还不是很完善,还望各位批评指教。