SpringBoot項目:員工管理系統(業務)


7、登錄

業務流程

  1. index.html頁,輸入用戶名和密碼,點擊登錄;
    • 發起請求,對用戶名密碼進行判斷
  2. 登錄成功,跳轉到dashboard.html

7.1、准備:視圖控制器

  • 添加視圖控制器:MyMvcConfig中為dashboard頁面添加一個視圖映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
	...
    // dashboard頁
    registry.addViewController("/main").setViewName("dashboard");
}

7.2、准備:登錄業務

登錄功能需要驗證用戶名和密碼,所以需要補充一套相應的業務。

  • 自頂向下分析Controller 調 ServiceService 調 DAO
  • 自底向上編寫:先寫 DAO,再寫 Service,再寫 Controller
  1. EmployeeMapper

    /**
     * 查詢用戶:登錄功能
     *
     * @param name       員工名:用戶名
     * @param employeeId 員工ID:密碼
     * @return 待查詢員工
     */
    Employee getEmployeeForLogin(String name, String employeeId);
    
  2. EmployeeMapper.xml

    <select id="getEmployeeForLogin" resultMap="employeeMap">
        SELECT create_time,
               update_time,
               employee_id,
               name,
               email,
               gender,
               birthday,
               department_id
        FROM springboot_staff.employee
        WHERE name = #{name}
          and employee_id = #{employeeId}
    </select>
    
  3. EmployeeService:同 EmployeeMapper

  4. EmployeeServiceImpl

    @Override
    public Employee getEmployeeForLogin(String name, String employeeId) {
        return employeeMapper.getEmployeeForLogin(name, employeeId);
    }
    

7.3、接口

LoginController

  1. 判斷用戶名和密碼是否為空;
  2. 調用 Service,查詢數據庫中是否有匹配的員工;
  3. 設置頁面
    • 登錄成功:設置 Session重定向到目標頁(需要視圖控制器);
    • 登錄失敗:設置參數,轉發到首頁
/**
 * 登錄
 */
@PostMapping("/employee/login")
public String login(@RequestParam("username") String username,
                    @RequestParam("password") String password,
                    Model model, HttpSession session) {
    // 判空
    if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
        model.addAttribute("msg", "用戶名或密碼為空");
        return "index";
    }

    Employee employee = employeeService.getEmployeeForLogin(username, password);

    if (employee != null) {
        // 創建一個EmployeeConstant類,靜態變量作為常量
        session.setAttribute(EmployeeConstant.LOGIN_EMPLOYEE, employee);
        return "redirect:/main";
    } else {
        model.addAttribute("msg", "用戶名或密碼錯誤");
        return "index";
    }
}

/**
 * 注銷
 */
@GetMapping("/employee/logout")
public String logout(HttpSession session) {
    session.invalidate();
    return "redirect:/index.html";
}

7.4、頁面

index.html

  1. Thymeleaf 語法——鏈接 URL 表達式@{...}
  2. 提交方式:post
  3. 添加一個 p標簽,用於接收提示信息(如:用戶名密碼錯誤);
  4. 字段要求有 name 屬性,否則后台無法接收到;
<!-- 登錄 -->
<form class="form-signin" th:action="@{/employee/login}" method="post">
    ...
    <p style="color:red" th:text="${msg}"></p>
    <input name="username" ...>
    <input name="password" ...>
</form>

<!-- 注銷 -->
<a class="nav-link" href="/employee/logout">Sign out</a>

dashboard.html

  1. 如果跳轉到 dashboard 頁面 后沒有 CSS 樣式,在引入 CSS 文件的 link 標簽href 前添加/
  2. 成功登錄后,dashboard 頁面左上角展示當前登錄的員工名;
  3. Thymeleaf 語法——插入片段[[${對象.屬性}]]
<head>
	...
    <link href="/asserts/css/bootstrap.min.css" rel="stylesheet">
    <link href="/asserts/css/dashboard.css" rel="stylesheet">
</head>

<body>
    ...
    <div class="navbar-brand col-sm-3 col-md-2 mr-0">[[${session.loginEmployee.name}]]
    ...
</body>

image-20211022225603327

7.5、攔截器

SpringMVC 攔截器

  1. 編寫:根據 Session 是否為空,判斷用戶是否成功登入;
  2. 注冊:向注冊器中添加寫好的攔截器,攔截所有頁面,首頁和登錄請求除外;

LoginHandlerInterceptor

獲取 Session,判斷是否為空;

  1. Session 為空:用戶未登錄或已退出
    • 設置參數(提示信息),轉發到首頁;
    • 攔截請求
  2. Session 非空:用戶已登入
    • 放行請求
public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Employee loginEmployee = (Employee) request.getSession().getAttribute(EmployeeConstant.LOGIN_EMPLOYEE);

        if (loginEmployee == null) {
            request.setAttribute("msg", "沒有訪問權限,請登錄");
            // 跳轉到首頁,【/index.html】是視圖控制器,也可以填【/】
            request.getRequestDispatcher("/index.html").forward(request, response);
            return false;
        }
        return true;
    }
}

MyMvcConfig

  1. addInterceptor:添加攔截器;
  2. addPathPatterns:添加攔截的路徑,/**代表所有路徑;
  3. excludePathPatterns:添加排除的路徑,即不被攔截的路徑
@Override
public void addInterceptors(InterceptorRegistry registry) {
    LoginHandlerInterceptor loginHandlerInterceptor = new LoginHandlerInterceptor();

    registry.addInterceptor(loginHandlerInterceptor)
            .addPathPatterns("/**")
            .excludePathPatterns("/index.html", "/", "/employee/login", "/asserts/**");
}

image-20211022225854146

8、員工展示

業務流程

  1. dashboard.html頁,點擊員工列表;
    • 發起請求,查詢出所有員工列表;
  2. 跳轉到員工展示頁

8.1、接口

EmployeeController

  1. 調用 Service,查詢所有員工列表;
  2. Model 設置數據
  3. 跳轉頁面:list.html
@Controller
public class EmployeeController {

    @Resource
    EmployeeService employeeService;

    @RequestMapping("/employee/listEmployees")
    public String listEmployees(Model model) {

        List<Employee> employeeList = employeeService.listEmployees();
        model.addAttribute("employeeList", employeeList);

        return "list";
    }
}

8.2、頁面

dashboard.html

  • 調用接口/employee/listEmployees
<li class="nav-item">
   <a class="nav-link" href="/employee/listEmployees">
      <svg ...>
		...
      </svg>
      Employees
   </a>
</li>

list.html

  1. 迭代th:each="xxx:${Xxx}"
    • th:each="employee:${employeeList}"
    • 對於 employeeList 中的每個元素,每次循環迭代並賦給 employee
  2. 取屬性${xxx.getXxx}[[]]
    • employee.getEmployeeId()等,要求實體類有 getter
    • 三元運算符邏輯表達式?表達式1:表達式2
    • 日期工具類#dates.format(日期對象,格式)
  3. 注意
    • NPE:如getDepartment().getName(),如果有某個員工沒有部門,則變成null.getName()報錯
<table ...>
    <thead>
    <tr>
        <th>EmployeeID</th>
        <th>Name</th>
        <th>Email</th>
        <th>Gender</th>
        <th>Birthday</th>
        <th>Department</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="employee : ${employeeList}">
        <td th:text="${employee.getEmployeeId()}"></td>
        <td th:text="${employee.getName()}"></td>
        <td th:text="${employee.getEmail()}"></td>
        <td th:text="${employee.getGender()==1?'男':'女'}"></td>
        <td th:text="${#dates.format(employee.getBirthday(),'yyyy-MM-dd')}"></td>
        <td th:text="${employee.getDepartment().getName()}"></td>
    </tr>
    </tbody>
</table>

image-20211103164716458

9、添加員工

流程

  1. list.html:點擊員工添加按鈕
    • 發起請求,查詢部門列表,跳轉到員工添加頁面
  2. add.html:輸入員工的屬性,點擊添加
    • 發起請求,將屬性自動封裝為對象,跳轉到員工展示

9.1、接口

EmployeeController

  1. 前往頁面

    • get 請求
    • 查詢所有部門,Model 設置
    • 跳轉頁面
  2. 處理業務

    • post請求
    • 用實體類接收頁面字段(SpringMVC 6.1.3
      • 要求:提交的域名稱和實體類屬性名一致、實體類有 setter
/**
 * 前往員工添加頁
 *
 * @return 員工添加頁
 */
@GetMapping("/employee/addEmployee")
public String toAddEmployee(Model model) {
    List<Department> departmentList = departmentService.listDepartments();
    model.addAttribute("departmentList", departmentList);
    return "add";
}

/**
 * 員工添加業務
 *
 * @param employee 待添加員工
 * @return 重定向:員工展示頁
 */
@PostMapping("/employee/addEmployee")
public String addEmployee(Employee employee) {
    employeeService.insertEmployee(employee);

    return "redirect:/employee/listEmployees";
}

9.2、頁面

list.html

  • 添加員工按鈕:get 請求
<a class="btn btn-sm btn-success" th:href="@{/employee/addEmployee}">添加員工</a>

add.html

  1. 表單:post 請求
  2. name 屬性:要求表單域有該屬性,且屬性名與實體類屬性名一致;
  3. 日期格式:默認為yyyy/MM/dd
  4. department
    1. 獲取部門列表,迭代獲取部門名,作為下拉框選項;
    2. 提交到后台的是department_id,而不是整個部門;
<form action="/employee/addEmployee" method="post">

    <div class="form-group">
        <label>EmployeeID</label>
        <input type="text" class="form-control" placeholder="請輸入員工ID" name="employeeId">
    </div>
    <div class="form-group">
        <label>Name</label>
        <input type="text" class="form-control" placeholder="請輸入員工姓名" name="name">
    </div>
    <div class="form-group">
        <label>Email</label>
        <input type="email" class="form-control" placeholder="請輸入員工郵箱" name="email">
    </div>
    <div class="form-group">
        <label>Gender</label><br>
        <div class="form-check form-check-inline">
            <input class="form-check-input" type="radio" value="1" name="gender">
            <label class="form-check-label">男</label>
        </div>
        <div class="form-check form-check-inline">
            <input class="form-check-input" type="radio" value="0" name="gender">
            <label class="form-check-label">女</label>
        </div>
    </div>
    <div class="form-group">
        <label>Birthday</label>
        <input type="text" class="form-control" placeholder="請輸入員工生日" name="birthday">
    </div>
    <div class="form-group">
        <label>Department</label>
        <select class="form-control" name="department.departmentId">
            <option th:each="department:${departmentList}" th:text="${department.getName()}"
                    th:value="${department.getDepartmentId()}"></option>
        </select>
    </div>
    <button type="submit" class="btn btn-primary">添加</button>
</form>

image-20211103164821225

10、修改員工(改名)

本項目中,通過修改員工名來體現修改功能。

流程

  1. list.html:點擊編輯按鈕
    • 發起請求,傳遞employeeId並查詢員工,跳轉到員工編輯頁面
  2. update.html:輸入需要修改的屬性,點擊保存
    • 發起請求,修改屬性,跳轉到員工展示頁

10.1、接口

  1. 前往頁面
    • get 請求
    • RESTful風格,攜帶參數employeeId
    • 根據 employeeId 查詢 employee,Model設置
    • 跳轉頁面
  2. 處理業務
    • post請求
    • 用實體類接收頁面字段
      • 要求:提交的域名稱和實體類屬性名一致、實體類有 setter
/**
 * 前往員工更新頁
 *
 * @param employeeId 待更新員工ID
 * @return 員工更新頁
 */
@GetMapping("/employee/updateEmployee/{employeeId}")
public String toUpdateEmployee(@PathVariable String employeeId, Model model) {
    Employee employee = employeeService.getEmployee(employeeId);
    model.addAttribute("employee", employee);
    
    return "update";
}

/**
 * 員工更新業務
 *
 * @param employeeId 待更新員工ID
 * @param name       員工新名
 * @return 重定向:員工展示頁
 */
@PostMapping("/employee/updateEmployee")
public String updateEmployee(String employeeId, String name) {
    employeeService.updateEmployee(employeeId, name);

    return "redirect:/employee/listEmployees";
}

10.2、頁面

list.html

  • 添加編輯刪除按鈕:get請求

  • RESTful風格,傳參'URL/'+${參數}

    • "@{'/employee/updateEmployee/'+${employee.getEmployeeId()}}"
    <table class="table table-striped table-sm">
        <thead>
        <tr>
    		...
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="employee : ${employeeList}">
    		...
            <td>
                <!-- 編輯 -->
                <a th:href="@{'/employee/updateEmployee/'+${employee.getEmployeeId()}}"
                   class="btn btn-sm btn-primary">編輯</a>
                <!-- 刪除 -->
            </td>
        </tr>
        </tbody>
    </table>
    

image-20211103170239069

update.html

  1. 表單:post 請求;
  2. 獲取員工信息,展示到頁面;
  3. name 屬性:要求表單域有該屬性,且屬性名與接口方法參數列表一致;
<form action="/employee/updateEmployee" method="post">

    <div class="form-group">
        <label>EmployeeID</label>
        <input class="form-control" type="text" name="employeeId" th:value="${employee.getEmployeeId()}"
               placeholder="請輸入員工ID"
               readonly>
    </div>

    <div class="form-group">
        <label>Name</label>
        <input class="form-control" type="text" name="name" th:placeholder="'原員工名:'+${employee.getName()}">
    </div>

    <button type="submit" class="btn btn-primary">保存</button>
</form>

image-20211111123846225

11、刪除員工

流程

  1. list.html:點擊刪除按鈕
  2. 發起請求,傳遞 employeeId,刪除員工

11.1、接口

  1. 調用接口
    • get 請求
    • RESTful風格,攜帶參數 employeeId
  2. 處理業務
    • 接收頁面字段
    • 刪除員工
/**
 * 刪除員工
 * @param employeeId 待刪除員工ID
 * @return 重定向:員工展示頁
 */
@GetMapping("/employee/deleteEmployee/{employeeId}")
public String deleteEmployee(@PathVariable String employeeId){
    employeeService.deleteEmployee(employeeId);
    return "redirect:/employee/listEmployees";
}

11.2、頁面

list.html

<a class="btn btn-sm btn-danger"
   th:href="@{'/employee/deleteEmployee/'+${employee.getEmployeeId()}}">刪除</a>

12、小結

到此,一個簡易的 Spring Boot 員工管理系統搭建完畢。

主要技術

  • JDBC、MySQL、Druid數據源、MyBatis
  • Spring Boot
  • Thymeleaf模板引擎;

知識點

  1. 阿里巴巴編程規范;
  2. ORM原則、不同命名風格的映射處理;
  3. 常量類、工具類的使用;
  4. 整合Druid數據源、MyBatis;
  5. 一對多關系的映射處理;
  6. MVC模式:pojo/DAO-Service-Controller;
  7. 使用注解開發;
  8. Thymeleaf模板引擎的使用
    1. 視圖控制器
    2. 鏈接表達式
    3. 循環遍歷
    4. 頁面取值
  9. 攔截器
  10. RESTful風格:GetMapping、PostMapping、@PathVariable
  11. 前后台傳值:屬性、對象
  12. CRUD


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM