员工管理系统包括向数据库添加新员工、更新现有员工、删除员工、检索数据库中所有员工数据等操作表的形式,最后一个是删除所有员工。在本文中,我们将了解员工管理系统,例如EMS App 或 EMS。大多数情况下,这个 Spring boot Web 应用程序处理员工数据并对数据库中的每个员工记录执行不同的操作。
要了解此员工管理系统应用程序,您需要以下技术的基本知识:
- Spring Boot
- Thymeleaf
- MongoDB
- Other Spring MVC Patterns
- Bootstrap Framework
Spring Boot 用于创建 MVC 模式的 Web 应用,Thymeleaf 也用于在网页中生成动态 HTML 内容主要目的是将HTML页面与Spring框架集成,并使用MongoDB进行数据存储。在此员工管理系统应用程序中,我们收集了不同领域的员工数据,例如,
- 员工ID
- 员工姓名
- 员工电话号码
- 员工性别
- 员工工资(卢比)
- 员工角色
另一件事是员工 ID 是动态创建的,并与其他员工详细信息进行映射并插入到数据库中。在员工管理系统中,我们使用了Bootstrap框架进行响应式网页设计并使用模型。 Bootstrap 模型是动态 html 内容,当动态单击按钮时,模型将打开。
在此 Web 应用程序中,我们可以通过输入员工 ID 来删除员工,也可以通过提供具有现有员工 ID 的员工的新详细信息来更新员工,其他功能是我们可以通过输入 ,如果输入 yes,应用程序决定需要删除所有员工数据。现在我们将通过编码来完成所有这些事情,以便更好地理解。yes
项目步骤:
- 创建 Spring Stater 项目
- 在主应用程序包中创建控制器、pojo、存储库的包。
- 在controller包中创建一个EmployeeController类,然后在pojo包中创建一个Employee POJO类,然后在repo包中创建一个EmployeeRepo接口。之后在模板中创建一个 html 页面,并将其放置在项目资源文件夹中。
- 现在实现Controller层代码,之后我们还需要实现pojo类和其他一个接口。
- 完成后端功能后,接下来开发前端网页。
- 之后使用 Thymeleaf 集成后端和前端
- 之后,将整个项目作为 Spring Boot 应用运行
项目依赖:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
|
首先我们从实际需求出发,即对员工详细信息进行一些操作。在对员工详细信息进行操作之前,我们首先需要正确地了解员工详细信息。因此,我收集了员工的一些详细信息,例如 员工 ID、员工姓名、员工姓名、员工电话号码、员工性别、员工工资(卢比)以及最后一个员工角色 所有这些事情。现在在 POJO 类中声明这些字段,以便为每个字段执行 setter 和 getter 操作。
数据库连接
在Spring boot中,有一个文件是application.properties文件,该文件用于本项目中的数据库连接。在这个项目中我使用了 MongoDB。基于此,我在此文件中编写了一些用于数据库连接的属性。您可以在上面的项目文件夹结构图中观察到该文件。
# mongodb数据库属性 spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=ems
# thymeleaf配置 spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html
|
模型层
Employee.java 和ConfirmationForm.java 位于模型层下,用于在本项目中使用这些pojo 类来控制应用程序中的数据流。
员工.java
Employee.java 是一个类,其中包含雇员的所有详细信息以及 Employee java 类中每个字段的 setters 和 getters 方法,以及参数化构造函数和一个默认构造函数,我在此 POJO 中用于不同的操作(例如数据)插入、数据更新、数据删除等。 Spring Boot 中提供了一个依赖项,即 lombok。
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Data @AllArgsConstructor @NoArgsConstructor @Document(collection = "employee") public class Employee { @Id private String id; private String employeeName; private String employeeEmail; private Long employeePhone; private String employeeGender; private String employeeSalary; private String employeeRole; }
|
它提供了很多注释,但在这个pojo中我使用了@Data、@AllArgsConstructor、@NoArgsConstructor、@Document(collection=”employee)”。 @Data 注解用于管理 setter 和 getter 方法,@AllArgsConstructor 用于管理参数化构造函数,@NoArgsConstructor 用于管理默认构造函数,@Document(collection=”employee) 用于在 MongoDB 中创建文档。ConfirmationForm
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class ConfirmationForm { private String confirmation; }
|
这个Pojo 类用于通过在文本字段中键入“yes”来确认删除所有员工的数据。如果您在该文本字段中输入“是”,则您同意从数据库中删除所有员工的数据。我将在控制器层解释这个 pojo 类,以便更好地理解。
视图
一般来说,HTML、JSP等前端技术都属于Spring MVC中的View层。对于这个员工管理系统,我使用 HTML 作为视图,在 Thymeleaf 的帮助下向最终用户显示数据。在此 HTML 页面中,我创建了四个动态表单,用于从前端处理应用程序。每个页面根据其用途执行独特的操作。
index.htm
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"> <link rel="shortcut icon" href="https://cdn-icons-png.flaticon.com/512/470/470199.png"> <meta charset="UTF-8"> <title>EMS App</title> </head> <style> body { overflow-x: hidden; scroll-behavior: smooth; } nav { background-color: navy !important; } .navbar-brand { color: whitesmoke !important; font-size: 30px !important; font-weight: bold; } .card { box-shadow: rgba(14, 30, 37, 0.12) 1px 2px 2px 0px, rgba(14, 30, 37, 0.32) 1px 2px 2px 0px; } .card-body { text-align: center; } .table-responsive { box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 2px 6px 2px; } th { text-align: center; font-size: 18px !important; } td { text-align: center; font-size: 15px; font-weight: 500; } label { font-weight: 500; } </style> <body> <nav class="navbar navbar-expand-sm navbar-light mb-5"> <div class="container"> <a class="navbar-brand text-bold" href="#"><i class="fa fa-align-center" aria-hidden="true"> EMS</i></a> </div> </nav> <main> <div class="container p-4"> <div class="head_section"> <div class="row row-cols-1 row-cols-md-4 g-3"> <div class="col"> <a href="exampleModalToggle1" data-bs-toggle="modal" role="button" style="text-decoration: none; color: white;"> <div class="card h-100 bg-success"> <div class="card-body"> <h5 class="text-light"><i class="fa fa-plus"></i> Add Employee</h5> </div> </div> </a> </div> <div class="col"> <a href="exampleModalToggle2" data-bs-toggle="modal" role="button" style="text-decoration: none; color: white;"> <div class="card h-100 bg-primary"> <div class="card-body"> <h5 class="text-light"><i class="fa fa-area-chart" aria-hidden="true"></i> Update Employee</h5> </div> </div> </a> </div> <div class="col"> <a href="exampleModalToggle3" data-bs-toggle="modal" role="button" style="text-decoration: none; color: white;"> <div class="card h-100 bg-danger"> <div class="card-body"> <h5 class="text-light"><i class="fa fa-trash"></i> Delete Employee</h5> </div> </div> </a> </div> <div class="col"> <a href="deleteAllModal4" data-bs-toggle="modal" role="button" style="text-decoration: none; color: white;"> <div class="card h-100 bg-dark"> <div class="card-body"> <h5 class="text-light"><i class="fa fa-warning"></i> Delete All</h5> </div> </div> </a> </div> </div> </div> <br> <div class="items_table mt-5 mb-4"> <div class="table-responsive p-2"> <h4 class="text-center p-2 class=" p-1" mt-2" style="font-family:'Times New Roman', Times, serif; font-weight: bold;">Employee Management System</h4> <table class="table table-bordered table-hover mt-5"> <thead class="bg-warning"> <th>SI.NO</th> <th>ID</th> <th>Name</th> <th>Email</th> <th>Phone</th> <th>Gender</th> <th>Salary</th> <th>Role</th> </thead> <tbody> <tr th:each="employee, index : ${employees}"> <td th:text="${index.index + 1}"></td> <td th:text="${employee.id}"></td> <td th:text="${employee.employeeName}"></td> <td th:text="${employee.employeeEmail}"></td> <td th:text="${employee.employeePhone}"></td> <td th:text="${employee.employeeGender}"></td> <td th:text="${employee.employeeSalary}"></td> <td th:text="${employee.employeeRole+' Developer'}"></td> </tr> </tbody> </table> </div> </div> </div> </main> <!-- model for create--> <div class="modal fade" id="exampleModalToggle1" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-body"> <div th:if="${success}" class="alert alert-success" role="alert"> <p th:text="${success}"></p> </div> <form class="p-2" th:action="@{/create}" th:object="${employee}" method="post"> <center> <h4 style="font-family: 'Times New Roman', Times, serif;">Add Employee</h4> </center> <div class="row p-2"> <label class="p-1" for="employeeName">Employee Name</label> <input type="text" th:field="*{employeeName}" class="form-control" placeholder="employee name" required> </div> <div class="row p-2"> <label class="p-1" for="employeeEmail">Email</label> <input type="text" th:field="*{employeeEmail}" class="form-control" placeholder="email address" required> </div> <div class="row p-2"> <label class="p-1" for="employeePhone">Phone</label> <input type="tel" th:field="*{employeePhone}" class="form-control" placeholder="phone number" required> </div> <div class="row p-2"> <label class="p-1">Gender</label> <select th:field="*{employeeGender}" class="form-select" required> <option value="" selected>select option</option> <option value="Male">Male</option> <option value="Female">Female</option> </select> </div> <div class="row p-2"> <label class="p-1" for="employeeSalary">Phone</label> <input type="number" th:field="*{employeeSalary}" class="form-control" placeholder="salary" required> </div> <div class="row p-2"> <label class="p-1" for="employeeRole">Employee Role</label> <select th:field="*{employeeRole}" class="form-select" required> <option value="" selected>select option</option> <option value="Java">Java Developer</option> <option value="Python">Python Developer</option> <option value="Web">Web Developer</option> <option value="Android">Android Developer</option> <option value="UI">UI Developer</option> </select> </div> <button type="submit" class="btn btn-success mt-3 mb-2">Add Employee</button> </form> </div> </div> </div> </div> </div> <!-- model for update--> <div class="modal fade" id="exampleModalToggle2" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-body"> <form class="p-2" th:action="@{/update}" th:object="${employee}" method="post"> <!-- Check if errorMessage is present in the model and display it --> <div th:if="${errorMessage}" class="alert alert-danger" role="alert"> <p th:text="${errorMessage}"></p> </div> <center> <h4 style="font-family: 'Times New Roman', Times, serif;">Update Employee</h4> </center> <div class="row p-1"> <label class="p-1" for="id">Employee ID</label> <input type="text" th:field="*{id}" class="form-control" placeholder="employee id" required> </div> <div class="row p-1"> <label class="p-1" for="employeeName">Employee Name</label> <input type="text" th:field="*{employeeName}" class="form-control" placeholder="employee name" required> </div> <div class="row p-1"> <label class="p-1" for="employeeEmail">Email</label> <input type="text" th:field="*{employeeEmail}" class="form-control" placeholder="email address" required> </div> <div class="row p-1"> <label class="p-1" for="employeePhone">Phone</label> <input type="tel" th:field="*{employeePhone}" class="form-control" placeholder="phone number" required> </div> <div class="row p-1"> <label class="p-1">Gender</label> <select th:field="*{employeeGender}" class="form-select" required> <option value="" selected>select option</option> <option value="Male">Male</option> <option value="Female">Female</option> </select> </div> <div class="row p-1"> <label class="p-1" for="employeeSalary">Phone</label> <input type="number" th:field="*{employeeSalary}" class="form-control" placeholder="salary" required> </div> <div class="row p-1"> <label class="p-1" for="employeeRole">Employee Role</label> <select th:field="*{employeeRole}" class="form-select" required> <option value="" selected>select option</option> <option value="Java">Java Developer</option> <option value="Python">Python Developer</option> <option value="Web">Web Developer</option> <option value="Android">Android Developer</option> <option value="UI">UI Developer</option> </select> </div> <button type="submit" class="btn btn-primary mt-3 mb-2">Update Employee</button> </form> </div> </div> </div> </div> </div> <!-- model for delete--> <div class="modal fade" id="exampleModalToggle3" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-body"> <form class="p-2" th:action="@{/remove}" th:object="${employee}" method="post"> <!-- Alert message --> <div th:if="${alertMessage}" class="alert alert-danger"> <p th:text="${alertMessage}"></p> </div> <center> <h4 style="font-family: 'Times New Roman', Times, serif;">Delete Employee</h4> </center> <div class="row p-2"> <label class="p-1" for="id">Employee ID</label> <input type="text" th:field="*{id}" class="form-control" placeholder="employee id" required> </div> <button type="submit" class="btn btn-danger mt-3 mb-2">Delete Employee</button> </form> </div> </div> </div> </div> </div> <!-- Delete All employees--> <div class="modal fade" id="deleteAllModal4" aria-hidden="true" aria-labelledby="deleteAllModalLabe4" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-body"> <form class="p-2" th:action="@{/remove/all}" th:object="${confirmationForm}" method="post"> <center> <h4 style="font-family: 'Times New Roman', Times, serif;">Delete All Employees</h4> </center> <div class="row p-2"> <label class="p-3 text-warning" for="confirmation">Type 'Yes' For Confirmation</label> <input type="text" th:field="*{confirmation}" class="form-control" placeholder="confirmation" required> </div> <button type="submit" class="btn btn-dark mt-3 mb-2">Delete All Employees</button> </form> </div> </div> </div> </div> <!-- bootstrap js --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
|
在上面的 HTML 代码中,我将 Thymeleaf URL 附加到了 HTML 元素。最主要的是对于 th:acton 属性中的每个表单,我提供基于逻辑的控制器处理程序。现在 Thymeleaf 会处理它。存储库
在这个项目中,我创建了一个 Mongo 存储库来执行 CRUD 操作。 @Repository用于创建Mongo Repository。并且可以通过java 接口来使用所有CRUD操作。该接口扩展至Mongo Repository。
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; import com.ems.app.pojo.Employee; @Repository public interface EmployeeRepo extends MongoRepository<Employee, String>{ }
|
在上面的代码中,我创建了一个接口,EmployeeRepo,它扩展到 MongoRepository。我使用了 MongoDB,这就是为什么我在这里使用 Mongo Repository,对于其他数据库,还有一点不同的是 MongoRepository 采用两个参数,即第一个参数是名称POJO 类,用于对其执行操作。
第二个是 POJO 类中 id 的数据类型。在我的 Employee pojo 中,我将 id 声明为 String 数据类型,因为员工 id 包含字母和数字。该EmployeeRepo接口用于插入、删除、更新、检索数据。
控制器层
Controller层是在Spring boot中使用@Controller注解创建的。 Controller 类用于处理传入的 API 请求,并准备模型并返回要呈现的视图作为响应。在这个控制器类中,我在这里创建了整个项目逻辑。我将把这一层中的每一件事分成小块来解释。
EmployeeController.java
import java.util.List; import java.util.Optional; import java.util.Random; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.ems.app.pojo.ConfirmationForm; import com.ems.app.pojo.Employee; import com.ems.app.repo.EmployeeRepo; @Controller public class EmployeeController { @Autowired private EmployeeRepo employeeRepo; // display the html page @GetMapping("/") public String getIndex(Model model) { List<Employee> employeeList = employeeRepo.findAll(); model.addAttribute("employees", employeeList); model.addAttribute("employee", new Employee()); model.addAttribute("confirmationForm", new ConfirmationForm()); return "index"; } // Insert employee data @PostMapping("/create") public String newEmployee(Employee employee, Model model) { model.addAttribute("employee", new Employee()); // creating dynamic Employee ID String empId = "EMP"; Random random = new Random(); long randomNumber = 1000 + random.nextInt(9000); empId = empId + randomNumber; employee.setId(empId); // save the employee employeeRepo.save(employee); return "redirect:/"; } // update the existing employee @PostMapping("/update") public String updateEmployee(@ModelAttribute Employee employee, Model model) { model.addAttribute("employee", new Employee()); Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId()); // checking employee exist or not if (existingEmployee.isPresent()) { employeeRepo.save(employee); } else { model.addAttribute("errorMessage", "Employee with ID " + employee.getId() + " not found."); } return "redirect:/"; } // delete an employee by id @PostMapping("/remove") public String removeEmployee(Employee employee, Model model) { model.addAttribute("employee", new Employee()); Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId()); if (existingEmployee.isPresent()) { employeeRepo.deleteById(employee.getId()); } return "redirect:/"; } // delete all employees data by confromation @PostMapping("/remove/all") public String removeAll(@ModelAttribute ConfirmationForm confirmationForm, Model model) { String confirmation = confirmationForm.getConfirmation(); if ("Yes".equalsIgnoreCase(confirmation)) { employeeRepo.deleteAll(); } else { return "redirect:/"; } return "redirect:/"; } }
|
在上面的代码中,我为不同的目的实现了不同的处理程序。这里的Handler是指请求URL。在此我使用了超过 3 个处理程序,下面列出了这些处理程序。
- @GetMapping(“/”) 该处理程序用于显示 html 页面
- @PostMapping(“/create”) 该处理程序用于插入员工数据
- @PostMapping(“/update”) 该处理程序用于通过使用员工 ID 更新现有员工
- @PostMapping(“/remove”) 该处理程序用于通过使用员工 ID 删除员工
- @PostMapping(“/remove/all”) 该处理程序用于通过提供确认来删除所有员工详细信息
显示 HTML 页面
为了显示 HTML 页面,我使用 Thymeleaf 进行渲染。为此,我创建了一个 GET 处理程序,用于 GET 请求,该请求充当 HTTP GET 方法。
@GetMapping("/") public String getIndex(Model model) { List<Employee> employeeList = employeeRepo.findAll(); model.addAttribute("employees", employeeList); model.addAttribute("employee", new Employee()); model.addAttribute("confirmationForm", new ConfirmationForm()); return "index"; }
|
在上面的代码中,我创建了一个 String 类型的方法。
- 之后,我将 Model 类作为参数传递给此方法。该 Model 类用于创建模型属性,这些属性用于在 HTML 内容中呈现视图。
- 之后,我使用 EmployeeRepo 对象创建一个列表来收集所有员工数据。在此对象中,我使用了 findAll() 用于获取所有员工数据。
- 之后为employeeList 创建了一个员工模型属性。 此员工模型属性通过使用 Model 发送到 html 页面,然后在 HTML 页面中 Thymeleaf 保存此属性并以表格形式显示数据。我创建了另一个模型属性,即员工,用于处理来自 Thymeleaf Side 的员工 pojo 类。
- 最后我返回此方法的索引页。
插入员工数据
为了将员工数据插入数据库,我使用了 EmployeeRepo 对象,它提供了save() 用于将员工数据保存到数据库中的方法。
@PostMapping("/create") public String newEmployee(Employee employee, Model model) { model.addAttribute("employee", new Employee()); // creating dynamic Employee ID String empId = "EMP"; Random random = new Random(); long randomNumber = 1000 + random.nextInt(9000); empId = empId + randomNumber; employee.setId(empId); // save the employee employeeRepo.save(employee); return "redirect:/"; }
|
这里我创建了一个 POST 映射,因为我通过这种方法将数据发送到数据库中,这就是我在这里使用 post 映射的原因。
- 我还使用 Thymeleaf 创建了一个模型属性,用于在 HTML 页面中处理员工 pojo。
- 在我使用 Java 中的 Random 类创建了一个随机 Employee id 后。对于随机 ID,我将 EMP 作为员工 ID 的前缀,然后动态生成 4 位数字,
- 然后将它们连接起来。成功生成Employee ID后,使用setId()方法将此值设置为Employee pojo类中的id。
- 之后,我将员工数据保存到数据库中。在 HTML 页面中创建了一种用于收集员工数据的表单。
- 成功插入员工数据后,将显示在表格中。
更新员工数据
如果您想更新员工,您需要现有员工 ID,然后我们才能更新员工数据,否则无法更新。这是相同的插入数据,但在此方法中插入之前,我检查员工 ID 是否存在。如果存在,我会授予更新员工信息的权限。
@PostMapping("/update") public String updateEmployee(@ModelAttribute Employee employee, Model model) { model.addAttribute("employee", new Employee()); Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId()); // checking employee exist or not if (existingEmployee.isPresent()) { employeeRepo.save(employee); } else { model.addAttribute("errorMessage", "Employee with ID " + employee.getId() + " not found."); } return "redirect:/"; }
|
成功员工详细信息更新后重定向到索引页面,并且在表中可见。因为我使用后映射意味着我发布数据,这就是我使用此映射的原因。可以在 HTML 页面中使用 Thymeleaf。
删除员工数据
删除员工时,我们需要员工ID,只有员工ID才可以删除已有的员工,否则无法删除。成功删除后,结果会在 Employee 表中更新,为此我使用 Thymeleaf 来处理 Employee pojo 类。为此,使用后映射来比较员工 ID 和员工数据。
@PostMapping("/remove") public String removeEmployee(Employee employee, Model model) { model.addAttribute("employee", new Employee()); Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId()); if (existingEmployee.isPresent()) { employeeRepo.deleteById(employee.getId()); } return "redirect:/"; }
|
提供员工 ID 后,单击给定按钮 此按钮会触发 Thymeleaf。 Thymeleaf 将对员工模型属性执行操作。该员工属性是在控制器类上创建的。在此控制器类中,成功删除员工后,使用 EmployeeRepo 对象执行删除操作,此结果将更新到员工表中。
删除所有员工
删除所有员工的逻辑基于用户确认。确认只不过是在删除所有数据之前,应用程序会询问您的确认,如果您在给定的文本字段中键入“是”,则意味着您同意删除所有员工的数据。从 HTML 页面一侧,Thymeleaf 通过持有 ConfirmationForm pojo 来执行此操作。此ConfirmationForm 接受一个字符串。如果该字符串与 yes 匹配,则自动删除所有数据。
@PostMapping("/remove/all") public String removeAll(@ModelAttribute ConfirmationForm confirmationForm, Model model) { String confirmation = confirmationForm.getConfirmation(); if ("Yes".equalsIgnoreCase(confirmation)) { employeeRepo.deleteAll(); } else { return "redirect:/"; } return "redirect:/"; }
|