Java SSM練手小專案-手把手帶你搭建一個基於SSM框架的人力資源管理後臺系統

是Guava不是瓜娃發表於2018-03-11

前言

相信很多小夥伴在學習完SSM三大架構以後,不知道該如何找到一個簡單容易上手的專案進行實戰訓練,經常在部落格上看到一個不錯的專案下載下來以後全部都是程式碼,無處下手。因此本文力求以最簡單易懂的專案結構和程式碼搭建一個還較為完整(即從登入到退出的整個流程)的後臺系統。(適合新手)

整個專案的操作流程動態圖如下(由於CSDN對上傳圖片大小有限制,這裡錄製的gif畫面很不清晰,點選圖片檢視更清晰):
這裡寫圖片描述
(點選圖片檢視)

專案的整體結構:
這裡寫圖片描述
這裡寫圖片描述

用到的技術棧有:

  • 框架:SSM
  • 資料庫:MySQL
  • 前端框架:Bootstrap快速搭 搭建JSP頁面
  • 專案管理:MAVEN
  • 開發工具:Intellij IDEA
  • 開發環境:Windows

從這個專案中你可以完整獨立地體驗從前端到後臺的搭建過程,以及使用SSM框架完成後臺的CRUD整個流程。

一、準備

準備部分主要包括資料庫建表、SSM框架的搭建啟動。
1 資料庫建表
tbl_emp表:

DROP TABLE IF EXISTS `tbl_emp`;
CREATE TABLE `tbl_emp`(
	`emp_id` int(11) UNSIGNED NOT NULL auto_increment,
	`emp_name` VARCHAR(22) NOT NULL DEFAULT '',
  `emp_email` VARCHAR(256) NOT NULL DEFAULT '',
  `gender` CHAR(2) NOT NULL DEFAULT '',
   `department_id` int(11) NOT NULL DEFAULT 0,
	 PRIMARY KEY(`emp_id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;

tbl_dept表:

DROP TABLE IF EXISTS `tbl_dept`;
CREATE TABLE `tbl_dept`(
	`dept_id` int(11) UNSIGNED NOT NULL auto_increment,
  `dept_name` VARCHAR(255) NOT NULL DEFAULT '',
	`dept_leader` VARCHAR(255) NOT NULL DEFAULT '',
	PRIMARY KEY(`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

對應的實體類見bean/Employee.java和bean/Department.java。
(在測試部分,執行EmployeeMapperTest.java 和 DepartmentMapperTest.java,可以將資料插入到表中)

2 SSM專案搭建與啟動
(1)本次專案使用的是MAVEN進行JAR包的管理,首先匯入專案中可能用到的依賴包:
見pom.xml.

(2)Web專案的配置檔案:web.xml:
見WEB-INF/web.xml.

(3)Spring容器配置檔案:applicationContext.xml:
見resources/applicationContext.xml.

(4)SpringMVC配置檔案:springmvc.xml:
見resources/springmvc.xml.

3 測試
寫好上述配置檔案後,可以在controller目錄下新建TestController.java檔案和WEB-INF/jsp/test.jsp,啟動容器測試是否成功。

二、DAO層程式碼完成與測試

這一章主要完成資料庫底層的CRUD程式碼實現與測試工作。
1. MyBasits配置檔案
見resources/MyBatis.xml.

2. DAO層程式碼
首先編寫實體類Employee 與 表tbl_emp相關操作程式碼。
EmployeeMapper.java主要介面有:

int deleteOneById(@Param("empId") Integer empId);
int updateOneById(@Param("empId") Integer empId,
                   @Param("employee") Employee employee);
int insertOne(Employee employee);           
 Employee selectOneById(@Param("empId") Integer empId);
Employee selectOneByName(@Param("empName") String empName);
// 查詢帶有部門資訊的Employee
Employee selectWithDeptById(@Param("empId") Integer empId);
// 分頁查詢
List<Employee> selectByLimitAndOffset(@Param("limit") Integer limit,@Param("offset") Integer offset);
int countEmps();

具體實現參考EmployeeMapper.java與EmployeeMapper.xml中程式碼。

寫完後需要對實現的程式碼進行測試,以驗證程式碼的正確性。
測試用例程式碼見EmployeeMapperTest.java。

類似地,
實體類Department與 表tbl_dept相關操作程式碼實現也如上類似,具體實現見DepartmentMapper.java 與 DepartmentMapper.xml,測試用例程式碼見DepartmentMapperTest.java。

三、前端頁面的搭建

前端頁面實現的最終效果如下。
主頁面:
Alt text

員工操作頁面(部門操作頁面類似):
這裡寫圖片描述
(點選圖片檢視)

最後加上一個登陸頁面(比較簡單的頁面加上最簡單的登入判斷):
這裡寫圖片描述
(點選圖片檢視)

主要就是採用Bootstrap3去搭建這個前端頁面,然後再利用SSM框架+JSP完成從前端到後端的整個流程。
下面首先Bootstrap3去搭建前端頁面。

1 主頁面的靜態搭建

主頁面的HTML程式碼實現放在webapp/static/html/hrms_main.html,(此處僅僅為了方便檢視和參考)。
整個主頁面完成後,分別將其中公共部分的程式碼提取出來,如導航欄,左側欄,尾部這3個部分都屬於公共部分,
分別見hrms_head.html、hrms_foot.html、hrms_leftsidebar.html三個部分。

2 公共頁面的JSP實現及分層

下面將上述公共部分的HTML程式碼用JSP實現,詳細見WEB-INF/jsp/commom目錄下的head.jsp、foot.jsp、leftsidebar.jsp。

然後實現主頁面的內容,主要包括三個公共部分(導航欄+左側欄+尾部+輪播部分),實現效果如下:
這裡寫圖片描述
(點選圖片檢視)

新建main.jsp,將上述三個公共部分的程式碼用
<<%@ include file="./commom/xx.jsp"%>>引入,再用Bootstrap實現輪播圖部分即可,具體實現見main.jsp中程式碼。

3 員工操作/部門操作的靜態頁面實現

員工操作頁面與主頁面3個公共部分相同,不同之處在於中間部分展示的是員工資訊的表格顯示,而主頁面是一個輪播圖。
這裡寫圖片描述
(點選圖片檢視)

下面就將實現employeePage的頁面,詳細程式碼見employeePage.jsp(即將main.jsp中的輪播部分換成員工表單顯示部分即可)。

(為了方便對比與檢視,將實現的HTML部分程式碼留在了專案目錄中,
實現的HTML程式碼見WEB-INF/static/html/hrms_employee.html。
相應的部門顯示的頁面類似,
實現的HTML程式碼見WEB-INF/static/html/hrms_department.html。
然後將上述程式碼分別用JSP頁面實現,即對應的employeePage.jsp和departmentPage.jsp。)

四、員工CRUD操作前後端實現

1 員工資訊查詢的資料顯示

頁面搭建完成以後,就要將從後臺獲取到的資料展示在對應的頁面中。頁面資料展示部分主要實現是利用JSP的JSTL表示式和AJAX+jQuery,將從後臺獲取到的資料顯示在頁面對應的位置。

由於部門操作與員工操作類似,下面主要講解員工顯示頁面的實現。
整個流程是從資料庫中查詢到資料後,放在SpringMVC的ModelAndView中,然後前端通過JSTL就可以解析獲取到的結果集。
(1)首先寫一個JSON相關的操作類:JsonMsg.java。
(2)業務操作:EmployeeService.java;
(3)Controller類:EmployeeController.java;
EmployeeController.java中介面"“emp/getEmpList?pageNo=XXX”"是根據輸入的頁碼返回對應頁數的資料,然後用JSTL表示式進行解析顯示。

    @RequestMapping(value = "/getEmpList", method = RequestMethod.GET)
    public ModelAndView getEmp(@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo){
        ModelAndView mv = new ModelAndView("");
        int limit = 5;
        // 記錄的偏移量(即從第offset行記錄開始查詢),
        // 如第1頁是從第1行(offset=(21-1)*5=0,offset+1=0+1=1)開始查詢;
        // 第2頁從第6行(offset=(2-1)*5=5,offset+1=5+1=6)記錄開始查詢
        int offset = (pageNo-1)*limit;
        //獲取指定頁數包含的員工資訊
        List<Employee> employees = employeeService.getEmpList(offset, limit);
        //獲取總的記錄數
        int totalItems = employeeService.getEmpCount();
        //獲取總的頁數
        int temp = totalItems / limit;
        int totalPages = (totalItems % limit == 0) ? temp : temp+1;
        //當前頁數
        int curPage = pageNo;

        //將上述查詢結果放到Model中,在JSP頁面中可以進行展示
        mv.addObject("employees", employees)
                .addObject("totalItems", totalItems)
                .addObject("totalPages", totalPages)
                .addObject("curPage", curPage);
        return mv;
    }

然後在employeePage.jsp頁面上將後端的Modal中資料取出來進行顯示。
主要程式碼有:

<tbody>
	<c:forEach items="${employees}" var="emp">
		 <tr>
		     <td>${emp.empId}</td>
		     <td>${emp.empName}</td>
		     <td>${emp.empEmail}</td>
		     <td>${emp.gender == "M"? "女": "男"}</td>
		     <td>${emp.department.deptName}</td>
		     <td>
		         <a href="#" role="button" class="btn btn-primary">編輯</a>
		         <a href="#" role="button" class="btn btn-danger">刪除</a>
		      </td>
		</tr>
	</c:forEach>
</tbody>

<div class="table_items">
	當前第<span class="badge">${curPage}</span>頁,共有<span class="badge">${totalPage}</span>頁,總記錄數<span class="badge">${totalItems}</span>條。
</div>

(4)分頁欄的程式碼實現。
分頁欄完成效果如下:
這裡寫圖片描述
(點選圖片檢視)

關於分頁欄需要完成的需求有:

  • 當前頁需要啟用(主要是頁面上的1,2,3,4,5頁);
  • 在首頁(第1頁)的時候,<< 禁止點選;
  • 在末頁(最後一頁)的時候,>>禁止點選;
  • 預設顯示首頁資料;
  • 首頁,上一頁,末頁,下一頁新增事件,顯示對應頁碼資料
  • 中間頁每一頁,為其新增點選事件,並跳轉到對應頁面;
  • 左邊資訊欄中當前第X頁需要根據點選的頁數同步顯示。

主要的程式碼實現都是在前端使用jQuery+JSTL實現的。程式碼如下:

<div class="panel-body">
此處程式碼略
</div>

以及對應的jQuery實現上一頁、下一頁的操作:

$(function () {
        //上一頁
        var curPage = ${curPage};
        var totalPages = ${totalPages};
        $(".prePage").click(function () {
            if (curPage > 1){
                var pageNo = curPage-1;
                $(this).attr("href", "/emp/getEmpList?pageNo="+pageNo);
            }
        });
        //下一頁
        $(".nextPage").click(function () {
            if (curPage < totalPages){
                var pageNo = curPage+1;
                $(this).attr("href", "/emp/getEmpList?pageNo="+pageNo);
            }
        });
    })

最後在主頁面中的員工資訊加上一個指定連結,跳轉到當前員工資訊顯示的頁面(部門操作類似,不再贅述),以及點選公司LOGO的時候跳轉到主頁面。
程式碼如下:
head.jsp:

<script type="text/javascript">
    //跳轉到主頁面
    $("#company_logo").click(function () {
        $(this).attr("href", "/hrms/main");
    });

leftsidebar.jsp:

<script type="text/javascript">
    //跳轉到員工頁面
    $(".emp_info").click(function () {
        $(this).attr("href", "/hrms/emp/getEmpList");
    });
    //跳轉到部門頁面
    $(".dept_info").click(function () {
        $(this).attr("href", "/hrms/dept/getDeptList");
    });
</script>

至此,員工資訊的顯示部分基本完成。

2 員工新增

接下來將會實現員工的新增操作,以及對新增資料的簡單驗證。
完成的頁面效果如下:
這裡寫圖片描述
(點選圖片檢視)

主要完成的需求有:

  • (1)點選左側欄的員工新增按鈕,彈出員工新增的模態框頁面;
  • (2)對輸入的姓名和郵箱格式進行驗證,格式不正確,提示錯誤資訊;
  • (4) 對輸入的姓名進行姓名是否重複判斷,重複則提示重複資訊;
  • (5)新增成功後跳轉到新增記錄所在的頁面(即最後一頁);
  • (6)新增失敗則提示錯誤資訊。

後臺程式碼實現主要有:

    /**
     * 查詢輸入的員工姓名是否重複
     * @param empName
     * @return
     */
    @RequestMapping(value = "/checkEmpExists", method = RequestMethod.GET)
    @ResponseBody
    public JsonMsg checkEmpExists(@RequestParam("empName") String empName){
        //對輸入的姓名與郵箱格式進行驗證
        String regName = "(^[a-zA-Z0-9_-]{3,16}$)|(^[\\u2E80-\\u9FFF]{2,5})";
        if(!empName.matches(regName)){
            return JsonMsg.fail().addInfo("name_reg_error", "輸入姓名為2-5位中文或6-16位英文和數字組合");
        }
        Employee employee = employeeService.getEmpByName(empName);
        if (employee != null){
            return JsonMsg.fail().addInfo("name_reg_error", "使用者名稱重複");
        }else {
            return JsonMsg.success();
        }
    }

    /**
     * 新增記錄後,查詢最新的頁數
     * @return
     */
    @RequestMapping(value = "/getTotalPages", method = RequestMethod.GET)
    @ResponseBody
    public JsonMsg getTotalPage(){
        int totalItems = employeeService.getEmpCount();
        //獲取總的頁數
        int temp = totalItems / 5;
        int totalPages = (totalItems % 5 == 0) ? temp : temp+1;
        return JsonMsg.success().addInfo("totalPages", totalPages);
    }

    /**
     * 新增員工
     * @param employee 新增的員工資訊
     * @return
     */
    @RequestMapping(value = "/addEmp", method = RequestMethod.POST)
    @ResponseBody
    public JsonMsg addEmp(Employee employee){
        int res = employeeService.addEmp(employee);
        if (res == 1){
            return JsonMsg.success();
        }else {
            return JsonMsg.fail();
        }
    }

前端程式碼見employeeAdd.jsp。
主要是jQuey的操作,很多操作可以封裝成一個函式進行呼叫,例如錯誤資訊的顯示。本文為了便於檢視,沒有進行封裝。

3 員工更改

員工修改操作完成頁面如下:
這裡寫圖片描述
這裡寫圖片描述
(點選圖片檢視)

更改主要完成的需求有:

  • (1) 獲取點選修改員工的id與name;
  • (2) 根據id或name查詢出對應員工資訊進行回顯;
  • (3) 回顯部門列表;
  • (4) 進行修改,對修改的郵箱格式進行判斷;
  • (5) 點選更新按鈕,傳送AJAX請求到後臺進行儲存;
  • (6)更改成功後跳轉到當前更改頁面。

後臺程式碼實現主要有:

    /**
     * 更改員工資訊
     * @param empId
     * @param employee
     * @return
     */
    @RequestMapping(value ="/updateEmp/{empId}", method = RequestMethod.PUT)
    @ResponseBody
    public JsonMsg updateEmp(@PathVariable("empId") Integer empId,  Employee employee){
        int res = employeeService.updateEmpById(empId, employee);
        if (res != 1){
            return JsonMsg.fail().addInfo("emp_update_error", "更改異常");
        }
        return JsonMsg.success();
    }

前端頁面+jQuery程式碼見:employeeUpdate.jsp

4 員工刪除

員工刪除操作完成頁面如下:
這裡寫圖片描述
(點選圖片檢視)

刪除主要完成的需求有:

  • (1)彈出確認框:是否刪除XX資訊;
  • (2)傳送AJAX請求,執行刪除操作;
  • (3)刪除成功後,跳轉到當前頁。

後臺程式碼:

    /**
     * 員工刪除操作
     * @param empId
     * @return
     */
    @RequestMapping(value = "/deleteEmp/{empId}", method = RequestMethod.DELETE)
    @ResponseBody
    public JsonMsg deleteEmp(@PathVariable("empId") Integer empId){
        int res = employeeService.deleteEmpById(empId);
        if (res != 1){
            return JsonMsg.fail().addInfo("emp_del_error", "員工刪除異常");
        }
        return JsonMsg.success();
    }

前端頁面程式碼見employeePage.jsp:

    <!-- ==========================員工刪除操作=================================== -->
    $(".emp_delete_btn").click(function () {
        var curPage = ${curPage};
        var delEmpId = $(this).parent().parent().find("td:eq(0)").text();
        var delEmpName = $(this).parent().parent().find("td:eq(1)").text();
        if (confirm("確認刪除【" + delEmpName+ "】的資訊嗎?")){
            $.ajax({
                url:"/hrms/emp/deleteEmp/"+delEmpId,
                type:"DELETE",
                success:function (result) {
                    if (result.code == 100){
                        alert("刪除成功!");
                        window.location.href="/hrms/emp/getEmpList?pageNo="+curPage;
                    }else {
                        alert(result.extendInfo.emp_del_error);
                    }
                }
            });
        }
    });

至此,SSM專案的增刪改查操作也基本完成,部門操作與上類似,本文不再贅述,感興趣的可以略看Department相關操作的程式碼。

5 登入頁面

最後,為求專案的完整性,加上一個登陸頁面,實現的效果
圖如下:
這裡寫圖片描述
(點選圖片檢視)

後臺主要做了一個簡單的登入驗證,程式碼見LoginController.java:

    /**
     * 登入:跳轉到登入頁面
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(){
        return "login";
    }

    /**
     * 對登入頁面輸入的使用者名稱和密碼做簡單的判斷
     * @param request
     * @return
     */
    @RequestMapping(value = "/dologin", method = RequestMethod.POST)
    @ResponseBody
    public JsonMsg dologin(HttpServletRequest request){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println(username + password);
        if (!"admin1234".equals(username + password)){
            return JsonMsg.fail().addInfo("login_error", "輸入賬號使用者名稱與密碼不匹配,請重新輸入!");
        }
        return JsonMsg.success();
    }

    /**
     * 跳轉到主頁面
     * @return
     */
    @RequestMapping(value = "/main", method = RequestMethod.GET)
    public String main(){
        return "main";
    }

    /**
     * 退出登入:從主頁面跳轉到登入頁面
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(){
        return "login";
    }

前臺頁面見login.jsp程式碼;以及退出登入按鈕的操作見head.jsp:

//賬號退出
$(".hrms_logout").click(function () {
  window.location.href = "/hrms/logout";
});

注:
容器配置:
在這裡插入圖片描述

五、專案程式碼下載

最後,將本次專案的程式碼上傳到我的github當中,想要下載專案原始碼的話:戳這裡
如果覺得對你有幫助別忘了在我的github上隨手點個star,THX!

If any problem, contact me with QQ : 1032335358.(請註明來源於CSDN)

2018/03/09 in NJ.


【頁面404 fix】 - fix in 2019/01/31

這段時間比較忙,很多同學的評論都沒有來得及回覆,很是抱歉。
看了下評論,基本上都是登入無反應 和 點選頁面404的問題,404一般是絕對路徑的問題,可以在程式碼中加上絕對路徑就不會出錯。
在配置容器的時候,只要點上如下配置,即可解決上述問題。
在這裡插入圖片描述

相關文章