首页 > 其他分享 >SpringBoot(七)| 员工管理系统

SpringBoot(七)| 员工管理系统

时间:2025-01-04 09:03:18浏览次数:3  
标签:chartjs SpringBoot 管理系统 html 员工 animation login public 页面

(一)环境搭建

bootstrap模板: https://getbootstrap.com/docs/4.0/examples/

项目源码:https://pan.baidu.com/s/1xpuOl0OXvwOf50nsxD5sOw

总体项目结构:
在这里插入图片描述

1. 新建一个SpringBoot项目

在这里插入图片描述
在这里插入图片描述

选择配件时勾选SpringWeb和Thymeleaf

在这里插入图片描述

点击next,然后finish创建完成即可

2. 导入依赖和静态资源

导入 lombok 依赖,还要在 IDEA 上安装 lombok 插件

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

导入 Thymeleaf 模板依赖

<!--thymeleaf-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

将html静态资源放置templates目录下

将asserts目录下的css、img、js等静态资源放置static目录下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 模拟数据库

1. 创建数据库实体类

在主程序同级目录下新建 pojo 包,用来存放实体类

在 pojo 包下创建一个部门表 Department 和一个员工表 Employee
在这里插入图片描述

部门表:Department.java

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

员工表:employee.java

//员工表
@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();
    }
}
2. 编写dao层(模拟数据)

在主程序同级目录下新建dao包

然后分别编写DepartmentDao和EmployeeDao,并在其中模拟数据库的数据

DepartmentDao.java

//部门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> getDepartments() {
        return departments.values();
    }

    //通过id得到部分
    public Department getDepartmentById(Integer id) {
        return departments.get(id);
    }
}

EmployeeDao.java

//员工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", "A46294093@qq.com", 0, new Department(101, "教学部")));
        employees.put(1002, new Employee(1002, "BB", "B46294093@qq.com", 1, new Department(102, "市场部")));
        employees.put(1003, new Employee(1003, "CC", "C46294093@qq.com", 0, new Department(103, "教研部")));
        employees.put(1004, new Employee(1004, "DD", "D46294093@qq.com", 1, new Department(104, "运营部")));
        employees.put(1005, new Employee(1005, "EE", "E46294093@qq.com", 0, new Department(105, "后勤部")));
    }

    //主键自增
    private static Integer initId = 1006;
    //增加一个员工
    public void save(Employee employee) {
        if (employee.getId() == null) {
            employee.setId(initId++);
        }
        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 deleteEmployeeById(Integer id) {
        employees.remove(id);
    }

}

(二)首页实现

在主程序同级目录下新建config包用来存放自己的配置类

在其中新建一个自己的配置类MyMvcConfig,进行视图跳转

1. 视图解析

package com.zsr.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

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

index.html

<!DOCTYPE html>
<html lang="en">
	<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>Signin Template for Bootstrap</title>
		<!-- Bootstrap core CSS -->
		<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
		<!-- Custom styles for this template -->
		<link th:href="@{/css/signin.css}" rel="stylesheet">
	</head>

	<body class="text-center">
		<form class="form-signin" th:action="@{/user/login}">
			<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">"Please sign in</h1>
			<!--如果msg的值为空,则不显示消息-->
			<p style="color: red" th:text = "${msg}" th:if="${not #strings.isEmpty(msg)}" ></p>
			<label class="sr-only" th:text="#{login.username}">Username</label>
			<input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
			<label class="sr-only"  th:text="#{login.password}">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(l='zh_CN')}">中文</a>
			<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
		</form>

	</body>

</html>

我们启动主程序访问测试一下,访问localhost:8080/或者locahost:8080/index.html
出现以下页面则成功
在这里插入图片描述

上述测试可以看到页面有图片没有加载出来,且没有css和js的样式,这就是因为我们html页面中静态资源引入的语法出了问题,在SpringBoot中,推荐使用Thymeleaf作为模板引擎,我们将其中的语法改为Thymeleaf,所有页面的静态资源都需要使用其接管

意所有html都需要引入Thymeleaf命名空间

xmlns:th="http://www.thymeleaf.org"

然后修改所有页面静态资源的引入,使用@{…} 链接表达式

例如 index.html 中:

注意:第一个 / 代表项目的 classpath,也就是这里的 resources 目录
在这里插入图片描述

2. 修改 html 的引用静态资源 为 Thymeleaf 动态引用,为了防止在不同根目录下找不到静态资源

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.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>Signin Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
   </head>

   <body class="text-center">
      <form class="form-signin" action="dashboard.html">
         <img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
         <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
         <label class="sr-only">Username</label>
         <input type="text" class="form-control" placeholder="Username" required="" autofocus="">
         <label class="sr-only">Password</label>
         <input type="password" class="form-control" placeholder="Password" required="">
         <div class="checkbox mb-3">
            <label>
          <input type="checkbox" value="remember-me"> Remember me
        </label>
         </div>
         <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
         <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
         <a class="btn btn-sm">中文</a>
         <a class="btn btn-sm">English</a>
      </form>

   </body>

</html>

其他页面亦是如此,再次测试访问,正确显示页面
在这里插入图片描述

404.html

<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
         <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Company 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" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
            </li>
         </ul>
      </nav>

      <div class="container-fluid">
         <div class="row">
            <nav class="col-md-2 d-none d-md-block bg-light sidebar">
               <div class="sidebar-sticky">
                  <ul class="nav flex-column">
                     <li class="nav-item">
                        <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
                              <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
                              <polyline points="9 22 9 12 15 12 15 22"></polyline>
                           </svg>
                           Dashboard <span class="sr-only">(current)</span>
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
                              <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                              <polyline points="13 2 13 9 20 9"></polyline>
                           </svg>
                           Orders
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart">
                              <circle cx="9" cy="21" r="1"></circle>
                              <circle cx="20" cy="21" r="1"></circle>
                              <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                           </svg>
                           Products
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
                              <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                              <circle cx="9" cy="7" r="4"></circle>
                              <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                              <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                           </svg>
                           Customers
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
                              <line x1="18" y1="20" x2="18" y2="10"></line>
                              <line x1="12" y1="20" x2="12" y2="4"></line>
                              <line x1="6" y1="20" x2="6" y2="14"></line>
                           </svg>
                           Reports
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
                              <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                              <polyline points="2 17 12 22 22 17"></polyline>
                              <polyline points="2 12 12 17 22 12"></polyline>
                           </svg>
                           Integrations
                        </a>
                     </li>
                  </ul>

                  <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
              <span>Saved reports</span>
              <a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
              </a>
            </h6>
                  <ul class="nav flex-column mb-2">
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Current month
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Last quarter
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Social engagement
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Year-end sale
                        </a>
                     </li>
                  </ul>
               </div>
            </nav>

            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <h1>404</h1>
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}" ></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}" ></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}" ></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>

dashboard.html

<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
         <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Company 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" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
            </li>
         </ul>
      </nav>

      <div class="container-fluid">
         <div class="row">
            <nav class="col-md-2 d-none d-md-block bg-light sidebar">
               <div class="sidebar-sticky">
                  <ul class="nav flex-column">
                     <li class="nav-item">
                        <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
                              <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
                              <polyline points="9 22 9 12 15 12 15 22"></polyline>
                           </svg>
                           Dashboard <span class="sr-only">(current)</span>
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
                              <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                              <polyline points="13 2 13 9 20 9"></polyline>
                           </svg>
                           Orders
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart">
                              <circle cx="9" cy="21" r="1"></circle>
                              <circle cx="20" cy="21" r="1"></circle>
                              <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                           </svg>
                           Products
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
                              <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                              <circle cx="9" cy="7" r="4"></circle>
                              <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                              <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                           </svg>
                           Customers
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
                              <line x1="18" y1="20" x2="18" y2="10"></line>
                              <line x1="12" y1="20" x2="12" y2="4"></line>
                              <line x1="6" y1="20" x2="6" y2="14"></line>
                           </svg>
                           Reports
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
                              <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                              <polyline points="2 17 12 22 22 17"></polyline>
                              <polyline points="2 12 12 17 22 12"></polyline>
                           </svg>
                           Integrations
                        </a>
                     </li>
                  </ul>

                  <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
              <span>Saved reports</span>
              <a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
              </a>
            </h6>
                  <ul class="nav flex-column mb-2">
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Current month
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Last quarter
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Social engagement
                        </a>
                     </li>
                     <li class="nav-item">
                        <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                              <polyline points="14 2 14 8 20 8"></polyline>
                              <line x1="16" y1="13" x2="8" y2="13"></line>
                              <line x1="16" y1="17" x2="8" y2="17"></line>
                              <polyline points="10 9 9 9 8 9"></polyline>
                           </svg>
                           Year-end sale
                        </a>
                     </li>
                  </ul>
               </div>
            </nav>

            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <div class="chartjs-size-monitor" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
                  <div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
                     <div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div>
                  </div>
                  <div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
                     <div style="position:absolute;width:200%;height:200%;left:0; top:0"></div>
                  </div>
               </div>
               <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
                  <h1 class="h2">Dashboard</h1>
                  <div class="btn-toolbar mb-2 mb-md-0">
                     <div class="btn-group mr-2">
                        <button class="btn btn-sm btn-outline-secondary">Share</button>
                        <button class="btn btn-sm btn-outline-secondary">Export</button>
                     </div>
                     <button class="btn btn-sm btn-outline-secondary dropdown-toggle">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>
                This week
              </button>
                  </div>
               </div>

               <canvas class="my-4 chartjs-render-monitor" id="myChart" width="1076" height="454" style="display: block; width: 1076px; height: 454px;"></canvas>

               
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}" ></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}" ></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}" ></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>

注意点: 所有页面的静态资源都需要使用 Thymeleaf 接管;@{}

(三)页面国际化

国际化:internationalization(简称 i18n,以 i 为开头,n 为结尾,中间18个字母)

在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。

我们需要使前端页面国际化,在此之前IDEA需要先安装 Resource Bundle Editor 插件来实现 properties 文件的可视化界面
在这里插入图片描述

1. 统一properties编码

首先在IDEA中统一设置properties的编码为UTF-8
在这里插入图片描述

2. 配置文件编写

  1. 我们在 resources 资源文件下新建一个 i18n 目录,存放国际化配置文件

在这里插入图片描述
其中新建三个配置文件,用来配置语言:

  • login.properties:无语言配置时候生效
    login_en_US.properties:英文生效
    login_zh_CN.properties:中文生效
  1. 建立一个 login.properties 文件,还有一个 login_zh_CN.properties;发现 IDEA 自动识别了我们要做国际化操作;文件夹变了!(右键 Resource Bundle 'login' 可以直接创建 properties 文件)
    命名方式是下划线的组合:文件名_语言_国家.properties;以此方式命名,IDEA会帮我们识别这是个国际化配置包,自动绑定在一起转换成如下的模式:
    在这里插入图片描述

  2. 我们可以在这上面去新建一个文件;
    在这里插入图片描述

弹出如下页面:我们再添加一个英文的;此时只需要输入区域名即可创建成功,比如输入 en_US,就会自动识别
在这里插入图片描述
这样就快捷多了!
在这里插入图片描述

4、然后打开英文或者中文语言的配置文件,点击Resource Bundle进入可视化编辑页面(点开 properties,左下角是可视化配置)
在这里插入图片描述

进入到可视化编辑页面后,点击加号,添加属性,首先新建一个login.tip代表首页中的提示
在这里插入图片描述

然后对该提示分别做三种情况的语言配置,在三个对应的输入框输入即可(注意:IDEA2020.1可能无法保存,建议直接在配置文件中编写)
在这里插入图片描述
接下来再配置所有要转换语言的变量(注意:IDEA2020.1可能无法保存,建议直接在配置文件中编写)
在这里插入图片描述

5、然后去查看我们的配置文件;(不同的 properties 里有着刚才输入不同的配置)

login.properties :默认

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

login_en_US.properties 英文:

login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username

login_zh_CN.properties 中文:

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

3. 配置国际化资源文件名称

在Spring程序中,国际化主要是通过ResourceBundleMessageSource这个类来实现的
Spring Boot通过MessageSourceAutoConfiguration为我们自动配置好了管理国际化资源文件的组件

在IDEA中查看以下MessageSourceAutoConfiguration类

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {

	private static final Resource[] NO_RESOURCES = {};

	@Bean
	@ConfigurationProperties(prefix = "spring.messages")
	public MessageSourceProperties messageSourceProperties() {
		return new MessageSourceProperties();
	}

	@Bean
	public MessageSource messageSource(MessageSourceProperties properties) {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		if (StringUtils.hasText(properties.getBasename())) {
			messageSource.setBasenames(StringUtils
					.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
		}
		if (properties.getEncoding() != null) {
			messageSource.setDefaultEncoding(properties.getEncoding().name());
		}
		messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
		Duration cacheDuration = properties.getCacheDuration();
		if (cacheDuration != null) {
			messageSource.setCacheMillis(cacheDuration.toMillis());
		}
		messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
		messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
		return messageSource;
	}
	//......
}

主要了解messageSource()这个方法:

public MessageSource messageSource(MessageSourceProperties properties);

可以看到,它的参数为MessageSourceProperties对象,我们看看这个类

public class MessageSourceProperties {

	/**
	 * Comma-separated list of basenames (essentially a fully-qualified classpath
	 * location), each following the ResourceBundle convention with relaxed support for
	 * slash based locations. If it doesn't contain a package qualifier (such as
	 * "org.mypackage"), it will be resolved from the classpath root.
	 */
	private String basename = "messages";

	/**
	 * Message bundles encoding.
	 */
	private Charset encoding = StandardCharsets.UTF_8;

类中首先声明了一个属性basename,默认值为messages;

我们翻译其注释:
在这里插入图片描述

- 逗号分隔的基名列表(本质上是完全限定的类路径位置)
- 每个都遵循ResourceBundle约定,并轻松支持于斜杠的位置
- 如果不包含包限定符(例如"org.mypackage"),它将从类路径根目录中解析

意思是:

  • 如果你不在springboot配置文件中指定以.分隔开的国际化资源文件名称的话
  • 它默认会去类路径下找messages.properties作为国际化资源文件

这里我们自定义了国际化资源文件,因此我们需要在SpringBoot配置文件application.properties中加入以下配置指定我们配置文件的名称

# 我们配置文件的真实位置
spring.messages.basename=i18n.login

其中i18n是存放资源的文件夹名,login是资源文件的基本名称。


4. 首页获取显示国际化值

利用#{…} 消息表达式,去首页index.html获取国际化的值
在这里插入图片描述

重启项目,访问首页,可以发现已经自动识别为中文
在这里插入图片描述

5. 配置国际化组件实现中英文切换

1. 添加中英文切换标签链接

上述实现了登录首页显示为中文,我们在index.html页面中可以看到两个标签

<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>

也就对应着视图中的

在这里插入图片描述

那么我们怎么通过这两个标签实现中英文切换呢?

首先在这两个标签上加上跳转链接并带上相应的参数

<!--这里传入参数不需要使用?使用key=value-->
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
2. 自定义地区解析器组件

怎么实现我们自定义的地区解析器呢?我们首先来分析一波源码
在Spring中有关于国际化的两个类:

  • Locale:代表地区,每一个Locale对象都代表了一个特定的地理、政治和文化地区
  • LocaleResolver:地区解析器

首先搜索WebMvcAutoConfiguration,可以在其中找到关于一个方法 localeResolver()

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
    //如果用户配置了,则使用用户配置好的
   if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
      return new FixedLocaleResolver(this.mvcProperties.getLocale());
   }
    //用户没有配置,则使用默认的
   AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
   localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
   return localeResolver;
}

该方法就是获取LocaleResolver地区对象解析器:

  • 如果用户配置了则使用用户配置的地区解析器;
  • 如果用户没有配置,则使用默认的地区解析器

我们可以看到默认地区解析器的是AcceptHeaderLocaleResolver对象,我们点入该类查看源码
在这里插入图片描述

因此我们想要实现上述自定义的国际化资源生效,只需要编写一个自己的地区解析器,继承LocaleResolver接口,重写其方法即可

我们在config包下新建MyLocaleResolver,作为自己的国际化地区解析器
在这里插入图片描述

MyLocaleResolver.java

package com.kuang.config;

import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

//可以在链接上携带区域信息
public class MyLocaleResolver implements LocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //获取请求中的语言参数
        String language = request.getParameter("l");

        Locale locale = Locale.getDefault();//如果没有就使用默认的

        //如果请求的链接携带了国际化的参数
        if(!StringUtils.isEmpty(language)){
            //zh_CN
            String[] split = language.split("_");
            //国家,地区
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

我们在 index.html 中,编写了对应的请求跳转

  • 如果点击中文按钮,则跳转到 /index.html(l='zh_CN') 页面
  • 如果点击 English 按钮,则跳转到 /index.html(l='en_US') 页面
    在这里插入图片描述

修改首页的国际化部分(Thymeleaf 获取国际化内容:#{})

例如:
=============
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
改成
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
============
<input type="text" class="form-control" th:placeholder="Username" required="" autofocus="">
改成
<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
============
<input type="password" class="form-control" th:placeholder="Password" required="">
改成
<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
============
<input type="checkbox" value="remember-me"> Remember me
改成
<input type="checkbox" value="remember-me"> [[#{login.remember}]]
=============
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
改成
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>

因此我们自定义的地区解析器MyLocaleResolver中,需要处理这两个带参数的链接请求

package com.zsr.config;

import org.springframework.cglib.core.Local;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.servl et.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

public class MyLocaleResolver implements LocaleResolver {
    //解析请求
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //获取请求中的国际化参数
        String language = request.getParameter("l");
        //默认的地区
        Locale locale = Locale.getDefault();
        //如果请求的链接参数不为空,携带了国际化参数
        if (!StringUtils.isEmpty(language)) {
            String[] split = language.split("_");//zh_CN(语言_地区)
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在自己的MvcConofig配置类下添加bean;

//自定义的国际化组件生效
@Bean
public LocaleResolver localeResolver() {
    return new MyLocaleResolver();
}

在这里插入图片描述

我们重启项目,来访问一下,发现点击按钮可以实现成功切换!

点击中文按钮,跳转到http://localhost:8080/index.html?l=zh_CN,显示为中文
在这里插入图片描述

点击English按钮,跳转到http://localhost:8080/index.html?l=en_US,显示为英文
在这里插入图片描述

注意点:

  1. 我们需要配置 i18n 文件
  2. 我们如果需要在项目中进行按钮自动切换,我们需要自定义一个组件 LocaleResolver
  3. 记得将自己写的组件配置到 spring 容器中 @Bean
  4. #{} 使用国际化内容

(四)登录功能实现

登录,也就是当我们点击登录按钮的时候,会进入一个页面,这里进入 dashboard 页面

实现登录时对用户名密码判断,如果错误就返回错误信息,成功就重定向到首页

  1. 修改 index.html ,为用户名和密码输入框添加 name 属性,用来传参。并在主页设置一个 msg 来接收错误参数
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.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>Signin Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
   </head>

   <body class="text-center">
      <form class="form-signin" th:action="@{/user/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}">Please sign in</h1>
         <!--如果msg的值为空,则不显示消息-->
         <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
         <label class="sr-only">Username</label>
         <input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
         <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" th:text="#{login.btn}">Sign in</button>
         <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
         <a class="btn btn-sm" th:href="@{/index.html(lang='zh_CN')}">中文</a>
         <a class="btn btn-sm" th:href="@{/index.html(lang='en_US')}">English</a>
      </form>

   </body>

</html>
  1. 编写一个 LoginController

在主程序同级目录下新建controller包,在其中新建类loginController,处理登录请求

package com.zsr.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class LoginController {
    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
        //如果用户名和密码正确
        if ("admin".equals(username) && "123456".equals(password))
            return "dashboard";//跳转到dashboard页面
            //如果用户名或者密码不正确
        else {
            model.addAttribute("msg", "用户名或者密码错误");//显示错误信息
            return "index";//跳转到首页
        }
    }
}

然后我们在index.html首页中加一个标签用来显示controller返回的错误信息

<p style="color: red" th:text="${msg}"></p>

在这里插入图片描述
我们再测试一下,启动主程序,访问 localhost:8080

如果我们输入正确的用户名和密码
在这里插入图片描述
则重新跳转到dashboard页面,浏览器url为http://localhost:8080/user/login?username=admin&password=123456
在这里插入图片描述
随便输入错误的用户名12,输入错误的密码12

浏览器url为http://localhost:8080/user/login?username=12&password=123456,页面上附有错误提示信息
在这里插入图片描述

到此我们的登录功能实现完毕,但是有一个很大的问题,浏览器的url暴露了用户的用户名和密码,这在实际开发中可是重大的漏洞,泄露了用户信息,因此我们需要编写一个映射

我们在自定义的配置类MyMvcConfig中加一句代码,用来实现登录后的重定向

registry.addViewController("/main.html").setViewName("dashboard");

也就是访问/main.html页面就跳转到dashboard页面

然后我们稍稍修改一下LoginController,当登录成功时重定向到main.html页面,也就跳转到了dashboard页面

package com.zsr.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class LoginController {
    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
        //如果用户名和密码正确
        if ("admin".equals(username) && "123456".equals(password))
            return "redirect:/main.html";//重定向到main.html页面,也就是跳转到dashboard页面
            //如果用户名或者密码不正确
        else {
            model.addAttribute("msg", "用户名或者密码错误");//显示错误信息
            return "index";//跳转到首页
        }
    }
}

我们再次重启测试,输入正确的用户名和密码登陆成功后,浏览器不再携带泄露信息
在这里插入图片描述
但是这又出现了新的问题,无论登不登陆,我们访问localhost/main.html都会跳转到dashboard的页面,这就引入了接下来的拦截器


(五)登录拦截器

为了解决上述遗留的问题,我们需要自定义一个拦截器;
在config目录下,新建一个登录拦截器类LoginHandlerInterceptor

想要自定义拦截器,必须实现 HandlerInterceptor 接口

用户登录成功后,后台会得到用户信息;如果没有登录,则不会有任何的用户信息;

我们就可以利用这一点通过拦截器进行拦截:

  • 当用户登录时将用户信息存入session中,访问页面时首先判断session中有没有用户的信息
  • 如果没有,拦截器进行拦截;
  • 如果有,拦截器放行

因此我们首先在LoginController中当用户登录成功后,存入用户信息到session中

  1. 修改 LoginController,将登录成功后的用户名放在 Session 中
@RequestMapping("/user/login")
public String login(
        @RequestParam("username") String username,
        @RequestParam("password") String password,
        Model model,
        HttpSession session) {

    //具体的业务
    if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
        session.setAttribute("loginUser", username);
        return "redirect:/main.html";
    } else {
        // 告诉用户,登录失败
        model.addAttribute("msg", "用户名或者密码错误");
        return "index";
    }
}

然后再在实现自定义的登录拦截器,继承HandlerInterceptor接口

  • 其中获取存入的session进行判断,如果不为空,则放行;
  • 如果为空,则返回错误消息,并且返回到首页,不放行。
  1. 编写一个 LoginHandlerInterceptor
public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //登录成功之后,应该有用户的Session
        if (request.getSession().getAttribute("loginUser") == null) {
            request.setAttribute("msg", "权限不够,请先登录");
            request.getRequestDispatcher("/index.html").forward(request, response);
            return false;
        } else {
            return true;
        }
    }
}

然后配置到bean中注册,在MyMvcConfig配置类中,重写关于拦截器的方法,添加我们自定义的拦截器,注意屏蔽静态资源及主页以及相关请求的拦截

  1. 把该拦截器注册到容器中,并设置拦截规则
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginHandlerInterceptor())
            .addPathPatterns("/**").excludePathPatterns("/index.html", "/", "/user/login", "/asserts/**");
}

然后重启主程序进行测试,直接访问http://localhost:8080/main.html

在这里插入图片描述

提示权限不够,请先登录,我们登录一下
在这里插入图片描述
进入到dashboard页面

如果我们再直接重新访问http://localhost:8080/main.html,也可以直接直接进入到dashboard页面,这是因为session里面存入了用户的信息,拦截器放行通过
在这里插入图片描述

(七)账号注销

通过移除 Session 的 loginUser 来实现账号注销

  1. 在 LoginController中添加如下代码,
@RequestMapping("/user/out")
public String out(HttpSession session) {
    session.removeAttribute("loginUser");
    return "redirect:/";
}
  1. 修改 dashboard.html
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a>

<a class="nav-link" th:href="@{/user/out}">log out</a>

重启测试,登录成功后,点击 log out 即可退出到首页
在这里插入图片描述

(八)展示员工列表 — 查

1. 提取公共页面

在templates目录下新建一个commons包,其中新建commons.html用来放置公共页面代码
在这里插入图片描述
利用th:fragment标签抽取公共部分(顶部导航栏和侧边栏)

提取公共页面有利于我们代码的复用,简化各个 html 的代码量

在 templates 下创建 commons 文件夹,在里面创建一个 commons.html 来存放公共页面(由于头部导航栏和侧边栏在各个页面都存在,我们可以直接提取出来当做公共页面)

提取:th:fragment="topbar" 
     th:fragment="siderbar(active)"

调用:th:replace="~{commons/commons :: topbar}" 

如果要传递参数,可以直接使用()传参,接收判断即可
    
(传递不同参数)
th:replace="~{commons/commons :: siderbar(active='main.html')}"
th:replace="~{commons/commons :: siderbar(active='list.html')}"
    
(判断参数内容)
th:class="${active=='main.html' ? 'nav-link active' : 'nav-link'}"
th:class="${active=='list.html' ? 'nav-link active' : 'nav-link'}"

commons.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    
<!--顶部导航栏,利用th:fragment提取出来,命名为topbar-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
    <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Company
        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" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
        </li>
    </ul>
</nav>
    
<!--侧边栏,利用th:fragment提取出来,命名为sidebar-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="siderbar">
    <div class="sidebar-sticky">
        <ul class="nav flex-column">
            <li class="nav-item">
                <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-home">
                        <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
                        <polyline points="9 22 9 12 15 12 15 22"></polyline>
                    </svg>
                    Dashboard <span class="sr-only">(current)</span>
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file">
                        <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                        <polyline points="13 2 13 9 20 9"></polyline>
                    </svg>
                    Orders
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-shopping-cart">
                        <circle cx="9" cy="21" r="1"></circle>
                        <circle cx="20" cy="21" r="1"></circle>
                        <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                    </svg>
                    Products
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" th:href="@{/emps}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-users">
                        <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                        <circle cx="9" cy="7" r="4"></circle>
                        <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                        <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                    </svg>
                    Customers
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-bar-chart-2">
                        <line x1="18" y1="20" x2="18" y2="10"></line>
                        <line x1="12" y1="20" x2="12" y2="4"></line>
                        <line x1="6" y1="20" x2="6" y2="14"></line>
                    </svg>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-layers">
                        <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                        <polyline points="2 17 12 22 22 17"></polyline>
                        <polyline points="2 12 12 17 22 12"></polyline>
                    </svg>
                    Integrations
                </a>
            </li>
        </ul>

        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
            <span>Saved reports</span>
            <a class="d-flex align-items-center text-muted"
               href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                     stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                     class="feather feather-plus-circle">
                    <circle cx="12" cy="12" r="10"></circle>
                    <line x1="12" y1="8" x2="12" y2="16"></line>
                    <line x1="8" y1="12" x2="16" y2="12"></line>
                </svg>
            </a>
        </h6>
        <ul class="nav flex-column mb-2">
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Current month
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Last quarter
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Social engagement
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Year-end sale
                </a>
            </li>
        </ul>
    </div>
</nav>
</html>

然后删除dashboard.html和list.html中顶部导航栏和侧边栏的代码
在这里插入图片描述

我们再次重启主程序测试一下,登陆成功后,可以看到已经没有了顶部导航栏和侧边栏
在这里插入图片描述

这是因为我们删除了公共部分,还没有引入,我们分别在dashboard.html和list.html删除的部分插入提取出来的公共部分topbar和sidebar

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

在这里插入图片描述

将 list.html 放入 emp 文件夹下,在 dashboard.html 和 list.html 中调用公共页面

dashboard.html:

<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <div th:replace="~{commons/commons :: topbar}"></div>

      <div class="container-fluid">
         <div class="row">

            <!--传递参数active给组件-->
            <div th:replace="~{commons/commons :: siderbar(active='main.html')}"></div>


            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <div class="chartjs-size-monitor" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
                  <div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
                     <div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div>
                  </div>
                  <div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
                     <div style="position:absolute;width:200%;height:200%;left:0; top:0"></div>
                  </div>
               </div>
               <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
                  <h1 class="h2">Dashboard</h1>
                  <div class="btn-toolbar mb-2 mb-md-0">
                     <div class="btn-group mr-2">
                        <button class="btn btn-sm btn-outline-secondary">Share</button>
                        <button class="btn btn-sm btn-outline-secondary">Export</button>
                     </div>
                     <button class="btn btn-sm btn-outline-secondary dropdown-toggle">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>
                This week
              </button>
                  </div>
               </div>

               <canvas class="my-4 chartjs-render-monitor" id="myChart" width="1076" height="454" style="display: block; width: 1076px; height: 454px;"></canvas>

               
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}" ></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}" ></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}" ></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>

list.html:

<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
		<!-- Bootstrap core CSS -->
		<link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

		<!-- Custom styles for this template -->
		<link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
		<style type="text/css">
			/* Chart.js */
			
			@-webkit-keyframes chartjs-render-animation {
				from {
					opacity: 0.99
				}
				to {
					opacity: 1
				}
			}
			
			@keyframes chartjs-render-animation {
				from {
					opacity: 0.99
				}
				to {
					opacity: 1
				}
			}
			
			.chartjs-render-monitor {
				-webkit-animation: chartjs-render-animation 0.001s;
				animation: chartjs-render-animation 0.001s;
			}
		</style>
	</head>

	<body>
		<div th:replace="~{commons/commons :: topbar}"></div>

		<div class="container-fluid">
			<div class="row">

				<!--插入抽取的部分-->
				<div th:replace="~{commons/commons :: siderbar(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>
								</tr>
							</thead>
							<tbody>
								
							</tbody>
						</table>
					</div>
				</main>
			</div>
		</div>

		<!-- Bootstrap core JavaScript
    ================================================== -->
		<!-- Placed at the end of the document so the pages load faster -->
		<script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}"></script>
		<script type="text/javascript" th:src="@{/asserts/js/popper.min.js}"></script>
		<script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}"></script>

		<!-- Icons -->
		<script type="text/javascript" th:src="@{/asserts/js/feather.min.js}"></script>
		<script>
			feather.replace()
		</script>

		<!-- Graphs -->
		<script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}"></script>
		<script>
			var ctx = document.getElementById("myChart");
			var myChart = new Chart(ctx, {
				type: 'line',
				data: {
					labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
					datasets: [{
						data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
						lineTension: 0,
						backgroundColor: 'transparent',
						borderColor: '#007bff',
						borderWidth: 4,
						pointBackgroundColor: '#007bff'
					}]
				},
				options: {
					scales: {
						yAxes: [{
							ticks: {
								beginAtZero: false
							}
						}]
					},
					legend: {
						display: false,
					}
				}
			});
		</script>

	</body>

</html>

再次重启主程序进行测试,登陆成功后,成功看到侧边栏和顶部栏,代表我们插入成功
在这里插入图片描述

3. 点击高亮处理

在页面中,使高亮的代码是 class="nav-link active" 属性
在这里插入图片描述
我们可以传递参数判断点击了哪个标签实现相应的高亮

首先在dashboard.html的侧边栏标签传递参数active为dashboard.html
在这里插入图片描述

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

同样在list.html的侧边栏标签传递参数active为list.html
在这里插入图片描述

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

然后我们在公共页面commons.html相应标签部分利用thymeleaf接收参数active,利用三元运算符判断决定是否高亮
在这里插入图片描述

再次重启主程序测试,登录成功后,首先Dashboard高亮
在这里插入图片描述

再点击Customers,Customers高亮,成功
在这里插入图片描述

4. 显示员工信息

修改list.html页面,显示我们自己的数据值
在这里插入图片描述

修改完成后,重启主程序,登录完成后查看所有员工信息,成功显示
在这里插入图片描述

接下来修改一下性别的显示和date的显示,并添加编辑和删除两个标签,为后续做准备

<thead>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>department</th>
        <th>date</th>
        <th>操作</th>
    </tr>
</thead>
<tbody>
    <tr th:each="emp:${emps}">
        <td th:text="${emp.getId()}"></td>
        <td th:text="${emp.getLastName()}"></td>
        <td th:text="${emp.getEmail()}"></td>
        <td th:text="${emp.getGender()==0?'女':'男'}"></td>
        <td th:text="${emp.getDepartment().getDepartmentName()}"></td>
        <td th:text="${#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')}"></td>
        <td>
            <a class="btn btn-sm btn-primary">编辑</a>
            <a class="btn btn-sm btn-danger">删除</a>
        </td>
    </tr>
</tbody>

再次重启主程序测试,成功
在这里插入图片描述

(九) 增加员工实现 — 增

1. list页面增加添加员工按钮

首先在list.html页面增添一个增加员工按钮,点击该按钮时发起一个请求/add
在这里插入图片描述

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

在这里插入图片描述
然后编写对应的controller,处理点击添加员工的请求

这里通过get方式提交请求,在EmployeeController中添加一个方法add用来处理list页面点击提交按钮的操作,返回到add.html添加员工页面,我们即将创建

  1. 在 EmployeeController 类里加入跳转请求
@GetMapping("/add")
public String add(Model model) {
    //查出所有的部门信息,添加到departments中,用于前端接收
    Collection<Department> departments = departmentDao.getDepartments();
    model.addAttribute("departments", departments);
    return "emp/add";//返回到添加员工页面
}

注意:这里是 Get 方法


2. 创建添加员工页面add

  1. 在 templates/emp 下编写一个 add.html
    在这里插入图片描述
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <div th:replace="~{commons/commons :: topbar}"></div>

      <div class="container-fluid">
         <div class="row">

            <!--插入抽取的部分-->
            <div th:replace="~{commons/commons :: siderbar(active='list.html')}"></div>


            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <form th:action="@{/add}" method="post">
                  <div class="form-group">
                     <label>Last Name</label>
                     <input type="text" name="lastName" class="form-control" placeholder="Dt">
                  </div>
                  <div class="form-group">
                     <label>Email</label>
                     <input type="email" name="email" class="form-control" placeholder="746294093@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 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>
                  <div class="form-group">
                     <label>Department</label>
                      <!--我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
                     <select class="form-control" name="department.id">
                        <option th:each="dept : ${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
                     </select>
                  </div>
                  <div class="form-group">
                     <label>Birth</label>
                     <input type="text" name="birth" class="form-control" placeholder="yyyy/MM/dd or yyyy/MM/dd HH:mm:ss">
                  </div>
                  <button type="submit" class="btn btn-primary">添加</button>
               </form>
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}"></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}"></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}"></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}"></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}"></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>

我们重启主程序看看
在这里插入图片描述

点击添加员工,成功跳转到add.html页面
在这里插入图片描述

下拉框中的内容不应该是1、2、3、4、5;应该是所有的部门名,我们遍历得到

<!--其中th:value用来表示部门的id,我们实际传入的值为id-->
<option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>

重启测试,成功显示所有部门
在这里插入图片描述
到此,添加员工页面编写完成

3. add页面添加员工请求

在add.html页面,当我们填写完信息,点击添加按钮,应该完成添加返回到list页面,展示新的员工信息;因此在add.html点击添加按钮的一瞬间,我们同样发起一个请求/add,与上述提交按钮发出的请求路径一样,但这里发出的是post请求

在这里插入图片描述
然后编写对应的controller,同样在EmployeeController中添加一个方法addEmp用来处理点击添加按钮的操作

@PostMapping("/add")
public String addEmp(Employee employee) {
    employeeDao.addEmployee(employee);//添加一个员工
    return "redirect:/emps";//重定向到/emps,刷新列表,返回到list页面
}

我们重启主程序,进行测试,进入添加页面,填写相关信息,注意日期格式默认为yyyy/MM/dd
在这里插入图片描述

然后点击添加按钮,成功实现添加员工
在这里插入图片描述

我们也可以添加多个员工
在这里插入图片描述

  1. 我们可以在 application.properties中设置读取日期的格式
# 格式化时间格式
spring.mvc.format.date=yyyy-MM-dd

(十) 修改员工信息 — 改

1. list页面编辑按钮增添请求

在这里插入图片描述
当我们点击编辑标签时,应该跳转到编辑页面 edit.html(我们即将创建)进行编辑
因此首先将list.html页面的编辑标签添加href属性,实现点击请求/edit/id号到编辑页面

<a class="btn btn-sm btn-primary" th:href="@{/edit/{id}(id=${emp.getId()})}">编辑</a>
  1. 修改 list.html的编辑按钮为 a 标签
<a class="btn btn-sm btn-primary" th:href="@{/edit/{id}(id=${emp.getId()})}">编辑</a>

在这里插入图片描述

然后编写对应的controller,在EmployeeController中添加一个方法edit用来处理list页面点击编辑按钮的操作,返回到edit.html编辑员工页面,我们即将创建

  1. 在 EmployeeController 类里加入跳转请求
//restful风格接收参数
@RequestMapping("/edit/{id}")
public String edit(@PathVariable("id") int id, Model model) {
    //查询指定id的员工,添加到empByID中,用于前端接收
    Employee employeeByID = employeeDao.getEmployeeByID(id);
    model.addAttribute("empByID", employeeByID);
    //查出所有的部门信息,添加到departments中,用于前端接收
    Collection<Department> departments = departmentDao.getDepartments();
    model.addAttribute("departments", departments);
    return "/emp/edit";//返回到编辑员工页面
}

注意:这里是 Get 方法

2. 创建编辑员工页面edit

在templates/emp下新建一个 update.html
在这里插入图片描述

  1. 在 templates/emp 下编写一个 update.html
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <div th:replace="~{commons/commons :: topbar}"></div>

      <div class="container-fluid">
         <div class="row">

            <!--插入抽取的部分-->
            <div th:replace="~{commons/commons :: siderbar(active='list.html')}"></div>


            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <form th:action="@{/emp}" method="post">
                  <input type="hidden" th:value="${emp.getId()}" name="id">
                  <div class="form-group">
                     <label>Last Name</label>
                     <input type="text" th:value="${emp.getLastName()}" name="lastName" class="form-control" placeholder="Dt">
                  </div>
                  <div class="form-group">
                     <label>Email</label>
                     <input type="email" th:value="${emp.getEmail()}" name="email" class="form-control" placeholder="746294093@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 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>
                  <div class="form-group">
                     <label>Department</label>
                     <!--我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
                     <select class="form-control" name="department.id">
                        <option th:selected="${emp.getDepartment().getId()==dept.getId()}"
                              th:each="dept : ${departments}" th:text="${dept.getDepartmentName()}"
                               th:value="${dept.getId()}"></option>
                     </select>
                  </div>
                  <div class="form-group">
                     <label>Birth</label>
                     <input type="text" th:value="${#dates.format(emp.getBirth(), 'yyyy/MM/dd HH:mm:ss')}"
                           name="birth" class="form-control" placeholder="yyyy/MM/dd or yyyy/MM/dd HH:mm:ss">
                  </div>
                  <button type="submit" class="btn btn-primary">添加</button>
               </form>
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}"></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}"></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}"></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}"></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}"></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>
  1. 由于方法的复用,我们不需要写额外的请求方法来修改员工信息,直接调用增加员工的请求,效果是一致的。

因为dao层模拟数据库用的是Map,而Map的特点是:主键唯一。所以只要保持主键一致就能达到覆盖修改的效果,就不需要再单独编写新的方法

启动主程序测试,点击编辑1号用户
在这里插入图片描述

成功跳转到 update.html,且所选用户信息正确
在这里插入图片描述

但是日期的格式不太正确,我们规定一下显示的日期格式

<!--springboot默认的日期格式为yy/MM/dd-->
<input th:value="${#dates.format(empByID.getDate(),'yyyy/MM/dd')}" type="text" name="date" class="form-control"
       placeholder="birth:yy/MM/dd">

3. edit页面编辑完成提交请求

在edit.html点击修改按钮的一瞬间,我们需要返回到list页面,更新员工信息,因此我们需要添加href属性,实现点击按钮时发起一个请求/edit

在这里插入图片描述
然后编写对应的controller,处理点击修改按钮的请求

同样在EmployeeController中添加一个方法EditEmp用来处理edit页面点击添加的操作

@PostMapping("/add")
public String EditEmp(Employee employee) {
    employeeDao.addEmployee(employee);//添加一个员工
    return "redirect:/emps";//添加完成重定向到/emps,刷新列表
}

然后指定修改人的id

<input type="hidden" name="id" th:value="${empByID.getId()}">

重启测试,同样修改1号用户名称为dddd
在这里插入图片描述
然后点击修改
在这里插入图片描述
成功修改并返回到list.html


(十一) 删除员工实现 — 删

在这里插入图片描述
当我们点击删除标签时,应该发起一个请求,删除指定的用户,然后重新返回到list页面显示员工数据

  1. 修改 list.html 的删除按钮为 a 标签
<a class="btn btn-sm btn-success" th:href="@{/delete/{id}(id=${emp.getId()})}">删除</a>
  1. 在 EmployeeController 类里加入增加员工请求
@GetMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id) {
    employeeDao.deleteEmployeeByID(id);
    return "redirect:/emps";
}

重启测试,点击删除按钮即可删除指定员工


(十二) 404 处理

只需要在templates目录下新建一个error包,然后将404.html放入其中,报错SpringBoot就会自动找到这个页面
在这里插入图片描述

我们可以启动程序测试,随便访问一个不存在的页面
在这里插入图片描述

出现的404页面即是我们自己的404.html


  1. 在templates下建立一个error文件夹,把 404.html 放进去
    springboot会自动帮我们配置处理,在出现404的时候会自动跳转到我们写好的404.html中

  2. 修改404.html的公共页面

<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.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>Dashboard Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <link th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

      <!-- Custom styles for this template -->
      <link th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
      <style type="text/css">
         /* Chart.js */
         
         @-webkit-keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         @keyframes chartjs-render-animation {
            from {
               opacity: 0.99
            }
            to {
               opacity: 1
            }
         }
         
         .chartjs-render-monitor {
            -webkit-animation: chartjs-render-animation 0.001s;
            animation: chartjs-render-animation 0.001s;
         }
      </style>
   </head>

   <body>
      <div th:replace="~{commons/commons :: topbar}"></div>

      <div class="container-fluid">
         <div class="row">
            <!--插入抽取的部分-->
            <div th:replace="~{commons/commons :: siderbar(active='404.html')}"></div>

            <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
               <h1>404</h1>
            </main>
         </div>
      </div>

      <!-- Bootstrap core JavaScript
    ================================================== -->
      <!-- Placed at the end of the document so the pages load faster -->
      <script type="text/javascript" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/popper.min.js}" ></script>
      <script type="text/javascript" th:src="@{/asserts/js/bootstrap.min.js}" ></script>

      <!-- Icons -->
      <script type="text/javascript" th:src="@{/asserts/js/feather.min.js}" ></script>
      <script>
         feather.replace()
      </script>

      <!-- Graphs -->
      <script type="text/javascript" th:src="@{/asserts/js/Chart.min.js}" ></script>
      <script>
         var ctx = document.getElementById("myChart");
         var myChart = new Chart(ctx, {
            type: 'line',
            data: {
               labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
               datasets: [{
                  data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
                  lineTension: 0,
                  backgroundColor: 'transparent',
                  borderColor: '#007bff',
                  borderWidth: 4,
                  pointBackgroundColor: '#007bff'
               }]
            },
            options: {
               scales: {
                  yAxes: [{
                     ticks: {
                        beginAtZero: false
                     }
                  }]
               },
               legend: {
                  display: false,
               }
            }
         });
      </script>

   </body>

</html>

References

员工管理系统

狂神Spring Boot 员工管理系统 超详细完整实现教程(小白轻松上手~)

标签:chartjs,SpringBoot,管理系统,html,员工,animation,login,public,页面
From: https://blog.csdn.net/qq_46450354/article/details/143695354

相关文章

  • ssm毕设体育队训练的信息管理系统源码+程序+论文
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容选题背景关于体育队训练的信息管理系统的研究,现有研究主要集中在大型体育赛事的组织管理和运动员训练数据的分析上,专门针对体育队日常训练管理的信息系统研究......
  • 人事管理系统的设计与实现
    人事管理系统的设计与实现摘要:随着信息技术的快速发展,传统的信息管理方式已经无法满足现代企业的需求。本文通过开发一个基于B/S三层结构的人事管理系统,使用MySQL数据库和JSP技术,旨在提供一个高效、稳定并具有良好用户交互体验的管理平台。本系统不仅能够实现基本的人事管......
  • 基于SSM的图书馆图书借阅管理系统【附源码+文档】
    ......
  • Java毕业设计基于SpringBoot+Vue甜品店管理系统
    一、项目介绍开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven————————————————二、功能介绍1.高效的用户界面开发1.Vue是一个渐进式JavaScript框架,用于构......
  • Springboot(五十六)SpringBoot3集成SkyWalking
    这里我们将skywalking集成到Springboot中。关于docker部署skyWalking的相关问题,请移步《docker(二十八)docker-compose部署链路追踪SkyWalking》一:下载java-agents先放一下skyWalking的官网下载地址 Downloads|ApacheSkyWalking其他的版本的APM地址(这个我不需要,我......
  • 396_基于Spring Boot的薪酬管理系统
    目录系统展示开发背景代码实现项目案例 获取源码博主介绍:CodeMentor毕业设计领航者、全网关注者30W+群落,InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者,博客领航之星、开发者头条/腾讯云/AWS/Wired等平台优选内容创作者、深耕Web......
  • ssm医院门诊信息管理系统p4bcu--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景随着医疗行业的快速发展和人们对医疗服务质量要求的不断提高,医院门诊的管理面临着越来越大的挑战。传统的手工管理方式不仅效率低下,而......
  • SpringBoot 整合 Quartz 定时任务框架
    本文没有聊到 Java 其他的实现定时任务的方法啥的~,只是对使用Quartz做了一个小实践一、简单聊一聊QuartzQuartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz其实就是通过一个调度线程不断的扫描数据库......
  • 2025年flask宠物医院后台管理系统设计与实现 程序+论文 可用于计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景随着宠物经济的蓬勃发展,宠物医院作为宠物健康保障的重要一环,其管理效率和服务质量直接关系到宠物主人的满意度和宠物的健康福祉。当前,关于......
  • springboot毕设 课程教学评估数据分析 程序+论文
    系统程序文件列表开题报告内容研究背景在当今教育信息化快速发展的背景下,课程教学评估作为提升教学质量的重要手段,日益受到各界的广泛关注。传统的教学评估方式往往依赖于人工收集和处理数据,不仅效率低下,而且难以全面、准确地反映教学活动的真实情况。随着大数据技术和人工......