【SpringBoot--案例】员工管理

复制于此博客 戳戳戳

1.准备工作

1、前端页面的放置

  • 将html页面放入templates目录

  • 将css,js,img放入到static目录

    在这里插入图片描述

2、实体类的编写

  • Department

    //部门表
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Department {
        private Integer id;
        private String departmentName;
    }
    12345678
    
  • Employee

    //员工表
    @Data
    @NoArgsConstructor
    public class Employee {
        private Integer id;
        private String lastName;
        private String email;
        private Integer gender; //0:女,1:男
    
        private Department department;
        private Date birth;
    
        public Employee(Integer id, String lastName, String email, Integer gender, Department department) {
            this.id = id;
            this.lastName = lastName;
            this.email = email;
            this.gender = gender;
            this.department = department;
            //默认的创建日期
            this.birth = new Date();
        }
    }
    12345678910111213141516171819202122
    

3、dao层模拟数据库

  • DepartmentDao

    //部门Dao
    @Repository
    public class DepartmentDao {
    
        //模拟数据库数据
    
        private static Map<Integer, Department> departments = null;
    
        static {
            departments = new HashMap<Integer, Department>();//创建一个部门表
    
            departments.put(101,new Department(101,"教学部"));
            departments.put(102,new Department(102,"市场部"));
            departments.put(103,new Department(103,"教研部"));
            departments.put(104,new Department(104,"运营部"));
            departments.put(105,new Department(105,"后勤部"));
        }
    
        //获得所有部门信息
        public Collection<Department> getDepartment() {
            return departments.values();
        }
    
        //通过id得到部门
        public Department getDepartmentById(Integer id) {
            return departments.get(id);
        }
    }
    12345678910111213141516171819202122232425262728
    
  • EmployeeDao

    //员工Dao
    @Repository
    public class EmployeeDao {
    
        //模拟数据库数据
        private static Map<Integer, Employee> employees = null;
        //员工所属部门
        @Autowired
        private DepartmentDao departmentDao;
    
        static {
            employees = new HashMap<Integer, Employee>();//创建一个员工表
    
            employees.put(1001,new Employee(1001,"AA","A123456@qq.com",1,new Department(101,"教学部")));
            employees.put(1002,new Employee(1002,"BB","B123456@qq.com",0,new Department(102,"市场部")));
            employees.put(1003,new Employee(1003,"CC","C123456@qq.com",1,new Department(103,"教研部")));
            employees.put(1004,new Employee(1004,"DD","D123456@qq.com",0,new Department(104,"运营部")));
            employees.put(1005,new Employee(1005,"EE","E123456@qq.com",1,new Department(105,"后勤部")));
        }
    
        //主键自增
        private static Integer ininId = 1006;
    
        //增加一个员工
        public void save(Employee employee) {
            if (employee.getId() == null) {
                employee.setId(ininId++);
            }
            employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
    
            employees.put(employee.getId(),employee);
        }
    
        // 查询全部员工信息
        public Collection<Employee> getAll() {
            return employees.values();
        }
    
        // 通过id查询员工
        public Employee getEmployeeById(Integer id) {
            return employees.get(id);
        }
    
        //删除员工通过id
        public void delete(Integer id) {
            employees.remove(id);
        }
    }
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
    

4、目录结构

在这里插入图片描述

2.首页实现

第一种方式

创建一个IndexController,写一个返回首页的方法(不建议使用)

@Controller
public class IndexController{
    @RequestMapping({"/","/index.html"})
    public String index() {
        return "index";
    }
}
1234567

第二种方式

创建一个config目录,在里面写一个MyMvcConfig,里面重写addViewControllers方法

@Configuration
public class MyMvcConfig implements WebMvcConfigurer{
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
}
1234567

首页页面展示:

在这里插入图片描述

加载静态资源

1、导入thymeleaf包

<html lang="en" xmlns:th="http://www.thymeleaf.org">
1

2、将所有页面的静态资源使用thymeleaf接管

<!-- css的导入 -->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/css/signin.css}" rel="stylesheet">

<!-- 图片的导入 -->
<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">

<!-- js导入 -->
<script type="text/javascript" th:src="@{/js/jquery-3.2.1.slim.min.js}"></script>
<script type="text/javascript" th:src="@{/js/popper.min.js}"></script>
<script type="text/javascript" th:src="@{/js/bootstrap.min.js}"></script>

<script type="text/javascript" th:src="@{/js/feather.min.js}"></script>

<script type="text/javascript" th:src="@{/js/Chart.min.js}"></script>
123456789101112131415

静态资源目录

在这里插入图片描述

再次看一下首页页面

在这里插入图片描述

3.页面国际化

见页面国际化:https://blog.csdn.net/weixin_44635198/article/details/107581680

4.登录页面

1、首页登录页面表单的修改

<form class="form-signin" th:action="@{/user/login}">
    ......
    <!--如果msg的消息不为空,则显示这个消息-->
    <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty({msg})}"></p>
    <input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
    <input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required="">
	......
</form>        
12345678

注意:登录失败时的信息显示的书写(第4行内容)

2、写一个LoginController登录验证

@Controller
public class LoginController {

    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password")String password,
                        Model model,
                        HttpSession session) {
        //具体的业务,登录成功跳转到dashboard页面
        if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
            return "dashboard";
        } else {
            model.addAttribute("msg","用户名或者密码错误");
            return "index";
        }
    }
}
1234567891011121314151617

登录成功页面

在这里插入图片描述

登录失败页面

在这里插入图片描述

3、登录页面不友好(密码泄露)

在这里插入图片描述

4、解决3的密码泄露问题

  • 加一个main映射在MyMvcConfig中(第6行)

    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");
        }
    }
    12345678
    
  • 修改LoginController跳转页面代码(redirect跳转)

    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password")String password,
                        Model model) {
        //具体的业务,登录成功跳转到dashboard页面
        if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
            return "redirect:/main.html";
        } else {
            model.addAttribute("msg","用户名或者密码错误");
            return "index";
        }
    }
    123456789101112
    

    在这里插入图片描述

5、是否存在问题?(登录成功才可以进入main页面,否则直接输入http://localhost:8080/main.html就可以访问首页了),需要拦截器实现

5.登录拦截器

1、在LoginController中添加一个session判断登录(第11行)

@Controller
public class LoginController {

    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password")String password,
                        Model model,
                        HttpSession session) {
        //具体的业务,登录成功跳转到dashboard页面
        if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
            session.setAttribute("loginUser",username);
            return "redirect:/main.html";
        } else {
            model.addAttribute("msg","用户名或者密码错误");
            return "index";
        }
    }
}
123456789101112131415161718

2、在config页面写一个LoginHandlerInterceptor拦截器

public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 登录成功之后,应该有用户的session
        Object loginUser = request.getSession().getAttribute("loginUser");

        if (loginUser == null) {
            request.setAttribute("msg","没有权限,请先登录");
            request.getRequestDispatcher("/index.html").forward(request,response);
            return false;
        } else {
            return true;
        }
    }
}
12345678910111213141516

3、MyMvcConfig页面重写拦截器方法

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginHandlerInterceptor())
        .addPathPatterns("/**")
        .excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**");
}
123456

注意:静态资源的过滤,否则页面渲染效果会消失

4、在dashboard.html页面修改登录信息为session[[ ${session.loginUser} ]],登录成功之后会显示用户名

5、页面的展示

在这里插入图片描述

6.员工列表展示

后台编写

员工管理后台Controller编写

@Controller
public class EmployeeController {
    
    @Autowired
    EmployeeDao employeeDao;

    @RequestMapping("/emps")
    public String list(Model model) {
        Collection<Employee> employees = employeeDao.getAll();
        model.addAttribute("emps",employees);
        return "emp/list";
    }
}

1234567891011121314

提取公共页面

1、员工管理前端页面地址的修改(list.html和dashboard.html)@{/emps}

<li class="nav-item">
    <a class="nav-link" th:href="@{/emps}">
        ......
        员工管理
    </a>
</li>
123456

2、抽取公共的代码(list.html和dashboard.html)

  • dashboard.html页面

    <!--顶部导航栏-->
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
        <!--...-->
    </nav>
    
    <!--侧边栏-->
    <nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
       <!--...-->
    </nav>
    123456789
    
  • list.html

    <!--顶部导航栏-->
    <div th:insert="~{dashboard::topbar}"></div>
    
    
    <!--侧边栏-->
    <div th:insert="~{dashboard::sidebar}"></div>
    123456
    

3、进一步抽取公共的代码

  • templates目录下面创建commons目录,在commons目录下面创建commons.html放公共代码

    <!--只写改变的代码-->
    
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    
    <!--顶部导航栏-->
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
        .............
    </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="@{/index.html}">
                      	.............
                        首页 <span class="sr-only">(current)</span>
                    </a>
                </li>
                .............
                <li class="nav-item">
                    <a class="nav-link" th:href="@{/emps}">
                        .............
                        员工管理
                    </a>
                </li>
                .............
            </ul>
            .............
        </div>
    </nav>
    </html>
    123456789101112131415161718192021222324252627282930313233
    
  • dashboard.html和list.html页面一样

    <!--顶部导航栏-->
    <div th:replace="~{commons/commons::topbar}"></div>
    
    <!--侧边栏-->
    <div th:replace="~{commons/commons::sidebar}"></div>
    12345
    

    注意:replace和insert的效果一样,只不过insert会多套一层div

4、添加侧边栏点中高亮

  • 在dashboard.html和list.html页面中侧边栏传参(在括号里面直接传参)

    <!--侧边栏-->
    <div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>
    12
    
  • 在commons.html中接收参数并判断

    <!--侧边栏-->
    <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 th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/main.html}">
    
                      	.............
                        首页 <span class="sr-only">(current)</span>
                    </a>
                </li>
                .............
                <li class="nav-item">
                	<a th:class="${active=='list.html'?'nav-link active':'nav-link'}" th:href="@{/emps}">
    
                        .............
                        员工管理
                    </a>
                </li>
                .............
            </ul>
            .............
        </div>
    </nav>
    </html>
    12345678910111213141516171819202122232425
    

列表循环展示

员工列表循环(list.html)

<!--侧边栏-->
<div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
    <h2>Section title</h2>
    <div class="table-responsive">
        <table class="table table-striped table-sm">
            <thead>
                <tr>
                    <th>id</th>
                    <th>lastName</th>
                    <th>email</th>
                    <th>gender</th>
                    <th>department</th>
                    <th>birth</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr th:each="emp:${emps}">
                    <td th:text="${emp.getLastName()}"></td>
                    <td th:text="${emp.getEmail()}"></td>
                    <td th:text="${emp.getGender()==0?'':''}"></td>
                    <td th:text="${emp.department.getDepartmentName()}"></td>
                    <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
                    <td>
                        <button class="btn btn-sm btn-primary">编辑</button>
                        <button class="btn btn-sm btn-danger">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</main>
12345678910111213141516171819202122232425262728293031323334

页面展示

在这里插入图片描述

7.添加员工信息

按钮提交

list.html页面编写

<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">添加员工</a></h2>
1

添加的位置

在这里插入图片描述

跳转到添加页面

1、后台页面的编写(跳转到add.html页面 )

@GetMapping("/emp")
public String toAddPage(Model model) {
    //查出所有部门的信息
    Collection<Department> department = departmentDao.getDepartment();
    model.addAttribute("departments",department);
    return "emp/add";
}
1234567

2、add.html页面的编写(其他部分和list.html页面一样,只改main中的代码即可)

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
    <form th:action="@{/emp}" method="post">
        <div class="form-group">
            <label>LastName</label>
            <input type="text" name="lastName" class="form-control" placeholder="海绵宝宝">
        </div>
        <div class="form-group">
            <label>Email</label>
            <input type="email" name="email" class="form-control" placeholder="1176244270@qq.com">
        </div>
        <div class="form-group">
            <label>Gender</label><br>
            <div class="form-check form-check-inline">
                <input class="form-check-input" type="radio" name="gender" value="1">
                <label class="form-check-label"></label>
            </div>
        </div>
        <div class="form-check form-check-inline">
            <input class="form-check-input" type="radio" name="gender" value="0">
            <label class="form-check-label"></label>
        </div>
        <div class="form-group">
            <label>department</label>
            <select class="form-control" name="department.id">
                <!--我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
                <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}">1</option>
            </select>
        </div>
        <div class="form-group">
            <label>Birth</label>
            <input type="text" name="birth" class="form-control" placeholder="2020/07/25 18:00:00">
        </div>
        <button type="submit" class="btn btn-primary">添加</button>
    </form>
</main>
1234567891011121314151617181920212223242526272829303132333435

注意:下拉框提交的时候应提交一个属性,因为其在controller接收的是一个Employee,否则会报错

页面:

在这里插入图片描述

添加员工成功

后台页面的编写

@Autowired
DepartmentDao departmentDao;

@PostMapping("/emp")
public String addEmp(Employee employee) {
    employeeDao.save(employee);//调用底层业务方法保存员工信息
    return "redirect:/emps";
}
12345678

添加信息页面

在这里插入图片描述

添加成功页面

在这里插入图片描述

日期格式的修改

1、如果输入的日期格式为2020-01-01,则报错

在这里插入图片描述

2、application.properties文件中添加配置

  • 2.2.x版本之前

    spring.mvc.date-format=yyyy-MM-dd
    1
    
  • 2.2.x版本之后

    spring.mvc.format.date=yyyy-MM-dd
    1
    

8.修改员工信息

按钮提交

list.html页面编辑按钮的编写(’+‘ 报红别管)

<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>
1

跳转到修改页面

1、后台页面的接收参数(Restful风格)

// 去到员工的修改页面
@GetMapping("/emp/{id}")
public String toUpdateEmp(@PathVariable("id") Integer id, Model model) {
    //查出原来的数据
    Employee employee = employeeDao.getEmployeeById(id);
    model.addAttribute("emp",employee);
    //查出所有部门的信息
    Collection<Department> department = departmentDao.getDepartment();
    model.addAttribute("departments",department);
    return "emp/update";
}
1234567891011

2、update.html页面(main里面修改,其他和list.html页面一样)

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
    <form th:action="@{/updateEmp}" method="post">
        <input type="hidden" name="id" th:value="${emp.getId()}">
        <div class="form-group">
            <label>LastName</label>
            <input th:value="${emp.getLastName()}" type="text" name="lastName" class="form-control" placeholder="海绵宝宝">
        </div>
        <div class="form-group">
            <label>Email</label>
            <input th:value="${emp.getEmail()}" type="email" name="email" class="form-control" placeholder="1176244270@qq.com">
        </div>
        <div class="form-group">
            <label>Gender</label><br>
            <div class="form-check form-check-inline">
                <input th:checked="${emp.getGender()==1}" class="form-check-input" type="radio" name="gender" value="1">
                <label class="form-check-label"></label>
            </div>
        </div>
        <div class="form-check form-check-inline">
            <input th:checked="${emp.getGender()==0}" class="form-check-input" type="radio" name="gender" value="0">
            <label class="form-check-label"></label>
        </div>
        <div class="form-group">
            <label>department</label>
            <select class="form-control" name="department.id">
                <!--我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
                <option th:selected="${dept.getId()==emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
            </select>
        </div>
        <div class="form-group">
            <label>Birth</label>
            <input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}" type="text" name="birth" class="form-control" placeholder="2020-07-25 00:00:00">
        </div>
        <button type="submit" class="btn btn-primary">修改</button>
    </form>
</main>
123456789101112131415161718192021222324252627282930313233343536

在这里插入图片描述

修改员工成功

修改员工信息成功

@PostMapping("/updateEmp")
public String updateEmp(Employee employee) {
    employeeDao.save(employee);
    return "redirect:/emps";
}
12345

在这里插入图片描述

9.删除员工信息

按钮提交

list.html页面删除按钮的修改

<a class="btn btn-sm btn-danger" th:href="@{/delemp/}+${emp.getId()}">删除</a>
1

接收参数删除用工信息

// 删除员工
@GetMapping("/delemp/{id}")
public String deleteEmp(@PathVariable("id") Integer id) {
    employeeDao.delete(id);
    return "redirect:/emps";
}
123456

10.404页面

将404.html页面放入到templates目录下面的error目录中

在这里插入图片描述

错误运行页面

在这里插入图片描述

11.注销功能的实现

1、在commons.html中修改注销按钮

<a class="nav-link" th:href="@{/user/logout}">注销</a>
1

2、在LoginController.java中编写注销页面代码

@RequestMapping("/user/logout")
public String logout(HttpSession session) {
    session.invalidate();
    return "redirect:/index.html";
}
12345

在这里插入图片描述

12.如何写一个网站

  1. 前端搞定:页面长什么样子
  2. 设计数据库(数据库设计难点)
  3. 前端让他能够自动运行,独立化工程
  4. 数据接口如何对接:json,对象,all in one!
  5. 前后端联调测试

模板:

  1. 有一套自己熟悉的后台模板:工作必要!x-admin
  2. 前端页面:至少自己能够通过前端框架,组合出来一个网站页面
    • index
    • about
    • blog
    • post
    • user
  3. 让这个网站能够独立运行!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值