綜合練習筆記2(用戶管理系統)

綜合練習筆記(用戶管理系統)

1. 結合上次用戶信息列表展示案例進行簡單修改
    * 列表查詢
    * 登錄
    * 添加
    * 刪除
    * 修改


2. 增加更多複雜的功能
    * 刪除選中
    * 分頁查詢
    * 複雜條件查詢

用戶管理系統簡單的增刪改查功能的實現見此處。

複雜的功能

  • 刪除選中
    • 選中功能指的是複選框,複選框的提交方式是多個請求參數的形式:?id=1&id=2&id=3&id=4等;
    • *批量刪除功能的實現流程如圖所示批量刪除用戶功能流程圖
    • 請求參數提交成功後,需要再web層加一個Servlet進行處理,記爲DelSelectedServlet
      • DelSelectedServlet的主要步驟:
        • 獲取請求參數數組
        • 調用service層中的刪除多個用戶方法
        • 跳轉到頁面展示
      • service層中的批量刪除方法只需要在dao層刪除一個用戶的基礎上多次調用即可
      • 先將後臺的程序完成如下,在此之前也需要將複選框的name記爲uid,value記爲用戶的id
    //DelSelectedServle中的主要方法

    //1.獲取請求參數數組
    String[] uids = request.getParameterValues("uid");
    //2.調用service層中的刪除多個用戶方法
    UserService service = new UserServiceImpl();
    service.deleteUsers(uids);
    //3.重定向到userListServlet
    response.sendRedirect(request.getContextPath() + "/userListServlet");
    
    //service層中主要方法
    
    public void deleteUsers(String[] uids) {
        if (uids != null && uids.length > 0){
            for (int i = 0; i < uids.length; i++) {
                userDao.deleteUserById(Integer.parseInt(uids[i]));
            }
        }
    }
  • 此刪除選中功能的主要操作在於前端,如何才能提交多個複選框的請求參數?
    • 複選框本身其實就可以提交多個選中的參數,所以我們可以將這些複選框組合成一個表單中的複選框,即可以在整個table外套一個表單,這樣的話,只需要再設置點擊刪除選中按鈕時提交此表單即可;所以我們需要爲刪除選中按鈕添加點擊事件;
    • 設置全選與全不選複選框
        window.onload = function () {
            //獲取刪除選中按鈕,併爲其添加單擊事件
            document.getElementById("deleteSelected").onclick = function () {
                if(confirm("您確定要刪除所選條目嗎?")){
                    //前端處理提交空表單
                    //獲取並遍歷下面所有的複選框
                    var cbs = document.getElementsByName("uid");
                    var flag = false;
                    for(var i=0; i<cbs.length; i++){

                        if(cbs[i].checked){
                            flag = true;
                            break;
                        }
                    }
                    if(flag){
                        //獲取表單,並提交表單
                        document.getElementById("cbform").submit();
                    }
                }
            }

            //設置全選與全不選
            //1.獲取最上面的複選框設置其點擊事件
            document.getElementById("firstCb").onclick = function () {
                //2.獲取其他所有的複選框
                var cbs = document.getElementsByName("uid");
                //3.遍歷所有的複選框
                for(var i=0; i<cbs.length; i++){
                    //4.設置複選框狀態與第一個相同
                    cbs[i].checked = this.checked;
                }
            }

        }
  • 分頁查詢
    • 好處
      • 減小服務器開銷
      • 提高用戶體驗
    • 點擊list.jsp頁面中的頁碼來實現翻頁,本功能主要存在list.jsp頁面與服務器端的交互;
    • 數據交互分析
      • 服務器端主要需要輸出給頁面的數據包括:
        • 總記錄條數 totalCount

        • 總頁碼數 totalPage 總記錄條數 % 每頁條數 == 0 ? 總記錄條數 / 每頁條數 : 總記錄條數 / 每頁條數 + 1

        • 展示的用戶信息集合 List

        • 每頁條數 rows

        • 當前頁碼 currentPage

        • 需要設置一個文件,將分頁對象實體化;設置頁面對象爲 PageBean

    package domain;
    
    import java.util.List;
    
    /**
     * 分頁數據對象
     */
    public class PageBean<T> {
    private int totalCount;     //總記錄條數
    private int totalPage;      //總頁數
    private int rows;           //每頁顯示條數
    private int currentPage;    //當前頁碼
    private List<T> list;       //顯示的記錄集合

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "PageBean{" +
                "totalCount=" + totalCount +
                ", totalPage=" + totalPage +
                ", rows=" + rows +
                ", currentPage=" + currentPage +
                ", list=" + list +
                '}';
    }
}
        * 頁面需要提交給服務器端的數據包括:
            - 每頁條數 rows
            - 當前頁碼  currentPage
    * 點擊頁面的後的流程分析
        * web層  :表單提交數據給Servlet,記爲FindUserByPageServlet,該Servlet調用service層實現數據的查詢與封裝,將數據轉發給list.jsp
        * service層  :調用dao層實現數據庫中用戶信息的查找,將數據包裝爲PageBean對象,並返回給Servlet
        * dao層  :實現具體數據的查找
  • 分頁查詢功能的流程圖如下所示:
    分頁查詢功能流程圖
    • web層中FindUserByPageServlet的主要代碼如下所示
        //1.接收當前頁碼,每頁記錄條數
        String currentPage = request.getParameter("currentPage");
        String rows = request.getParameter("rows");
        //2.調用service層查詢用戶記錄數據
        UserService service = new UserServiceImpl();
        PageBean<User> pageBean = service.findUserByPage(currentPage, rows);
        System.out.println(pageBean);

        //3.將數據保存在request域
        request.setAttribute("pageBean", pageBean);
        //4.轉發到list.jsp頁面
        request.getRequestDispatcher("/list.jsp").forward(request, response);
  • service層中UserService主要代碼如下所示
    public PageBean<User> findUserByPage(String _currentPage, String _rows) {
        //1.創建空的PageBean對象
        PageBean<User> pageBean = new PageBean<User>();
        //2.設置當前頁碼及每頁記錄總數
        int currentPage = Integer.parseInt(_currentPage);
        int rows = Integer.parseInt(_rows);
        pageBean.setCurrentPage(currentPage);
        pageBean.setRows(rows);
        //3.調用dao層查詢用戶記錄總條數
        int totalCount = userDao.findTotalCount();
        pageBean.setTotalCount(totalCount);
        //4.調用dao層查詢要顯示的用戶到集合中
        int start = (currentPage-1) * rows;
        List<User> list = userDao.findUserByPage(start, rows);
        pageBean.setList(list);
        //5.計算總頁數
        int totalPage = totalCount % rows == 0 ? totalCount / rows : totalCount / rows + 1;
        pageBean.setTotalPage(totalPage);

       return pageBean;
    }
  • dao層中UserDao主要代碼如下所示
    public List<User> findUserByPage(int start, int rows) {
        String sql = "select * from user limit ?, ?";
        return (List<User>) template.query(sql, new BeanPropertyRowMapper<User>(User.class), start, rows);
    }
  • 以上主要實現了後端的數據操作,現已將包裝好的PageBean對象發送給了list.jsp頁面;借下來需要在list.jsp中完成信息的展示
    //設置分頁條如下
    <div>
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <c:if test="${pageBean.currentPage == 1}">
                        <li class="disabled">
                    </c:if>
                    <c:if test="${pageBean.currentPage != 1}">
                        <li>
                    </c:if>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pageBean.currentPage - 1}&rows=5" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
                <c:forEach begin="1" end="${pageBean.totalPage}" var="i">

                    <c:if test="${pageBean.currentPage == i}">
                        <li class="active"><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5">${i}</a></li>
                    </c:if>

                    <c:if test="${pageBean.currentPage != i}">
                        <li><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5">${i}</a></li>
                    </c:if>
                </c:forEach>


                <li>
                    <c:if test="${pageBean.currentPage == pageBean.totalPage}">
                        <li class="disabled">
                    </c:if>
                    <c:if test="${pageBean.currentPage != pageBean.totalPage}">
                        <li>
                    </c:if>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pageBean.currentPage + 1}&rows=5" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
                <span style="font-size: 25px; margin: 8px">
                    共${pageBean.totalCount}條記錄,共${pageBean.totalPage}</span>
            </ul>
        </nav>
    </div>
  • 在設置展示界面時也對後端進行了一些小的調整;主要是爲了防止空指針異常或者其他異常
    //在findUserByPageServlet中添加了以下判斷
    if(currentPage == null || "".equals(currentPage)){
        currentPage = "1";
    }
    if(rows == null || "".equals(rows)){    //默認每頁展示5條記錄
        rows = "5";
    }

    //在dao層的UserServiceImpl中對findUserByPage方法也添加了一些判斷,修改如下
    public PageBean<User> findUserByPage(String _currentPage, String _rows) {

        int currentPage = Integer.parseInt(_currentPage);
        int rows = Integer.parseInt(_rows);

        //1.創建空的PageBean對象
        PageBean<User> pageBean = new PageBean<User>();

        //若當前頁碼小於1,則設爲1
        if(currentPage < 1){
            currentPage =1;
        }
        //3.調用dao層查詢用戶記錄總條數
        int totalCount = userDao.findTotalCount();
        pageBean.setTotalCount(totalCount);

        //5.計算總頁數
        int totalPage = (totalCount % rows == 0) ? (totalCount / rows) : (totalCount / rows + 1);
        pageBean.setTotalPage(totalPage);

        //若當前頁面大於總頁數,則設爲總頁數
        if(currentPage > totalPage){
            currentPage = totalPage;
        }

        //2.設置當前頁碼及每頁記錄總數
        pageBean.setCurrentPage(currentPage);
        pageBean.setRows(rows);
        //4.調用dao層查詢要顯示的用戶到集合中
        int start = (currentPage-1) * rows;
        List<User> list = userDao.findUserByPage(start, rows);
        pageBean.setList(list);
       return pageBean;
    }
    
  • 複雜條件查詢
    • 此功能主要是完成多條件刪選查詢

    • 首先我們進行數據的交互分析

      • 表單輸入給服務器的數據非常簡單,當然就是這些框中的條件了
        • 當然,我們需要設置提交按鈕點擊後,表單的提交地址uri,以及爲各個框設置name
      • 服務器端可以將提交的數據通過map集合獲取,然後我們便在查詢數據時,需要加上所獲取的條件
        • 我們涉及到的數據庫的查詢有連個方法,一個是查詢數據的個數,一個是查詢數據的信息,並將其封裝爲list集合
        • 在這兩個方法中都涉及到一個sql的拼接問題;因爲查詢的條件個數並不確定
        • sql拼接的一個小的方法
          • 先定義一個基本sql = "selsec count(*) form user where 1 = 1 ";
          • 然後根據查詢的方法用StringBuffer將其進行拼接sb.append(" and " + key + " like ?");
          • 關於模糊查詢,需要用"%value%"這種方式,一定記得要加%
    • 由於此次功能與分頁查詢有相通之處,所以不需要再重新編寫servlet;只需要在上述分頁查詢的代碼中進行一些代碼的增加即可

    • 首先是查詢按鈕的修改

        <%--
            修改查詢表單的提交路徑
            爲各提交內容命名
            並加入查詢信息的回顯
        --%>
        <form class="form-inline" action="${pageContext.request.contextPath}/findUserByPageServlet" method="post">
            <div class="form-group">
                <label for="exampleInputName2">姓名</label>
                <input type="text" name="name" value="${condition.name[0]}" class="form-control" id="exampleInputName2">
            </div>
            <div class="form-group">
                <label for="exampleInputName3">籍貫</label>
                <input type="text" name="address" value="${condition.address[0]}" class="form-control" id="exampleInputName3">
            </div>
            <div class="form-group">
                <label for="exampleInputEmail2">郵箱</label>
                <input type="email" name="email" value="${condition.email[0]}" class="form-control" id="exampleInputEmail2">
            </div>
            <button type="submit" class="btn btn-default">查詢</button>
        </form>
  • 然後修改FindUserByPageServlet
        //設置請求編碼格式
        request.setCharacterEncoding("utf-8");

        //1.接收當前頁碼,每頁記錄條數
        String currentPage = request.getParameter("currentPage");
        String rows = request.getParameter("rows");
        //防止空指針異常,添加初始值
        if(currentPage == null || "".equals(currentPage)){
            currentPage = "1";
        }
        if(rows == null || "".equals(rows)){    //默認每頁展示5條記錄
            rows = "5";
        }

        System.out.println(currentPage + "--------" + rows);
        //接收請求參數map集合
        Map<String, String[]> condition = request.getParameterMap();

        //2.調用service層查詢用戶記錄數據,加入條件進行查詢
        UserService service = new UserServiceImpl();
        PageBean<User> pageBean = service.findUserByPage(currentPage, rows, condition);
        System.out.println(pageBean);

        //3.將數據保存在request域
        request.setAttribute("pageBean", pageBean);
        //也保存請求參數到request域,用以回顯
        request.setAttribute("condition", condition);
        //4.轉發到list.jsp頁面
        request.getRequestDispatcher("/list.jsp").forward(request, response);
  • 在FindUserByPageServlet中,我們修改了一個方法的參數,加入了條件查詢,我們可以直接重構此方法,也可以重載此方法,我這裏就再重新編寫一下這個方法
    
    public PageBean<User> findUserByPage(String _currentPage, String _rows, Map<String, String[]> condition) {
        
        // 創建新的PageBean對象
        PageBean<User> pageBean = new PageBean<>();

        int currentPage = Integer.parseInt(_currentPage);
        int rows = Integer.parseInt(_rows);

        //調用dao層查詢用戶記錄總條數
        int totalCount = userDao.findTotalCount(condition);
        //計算總頁數
        int totalPage = (totalCount % rows == 0) ? (totalCount / rows) : (totalCount / rows + 1);

        //解決沒有符合條件數據的情況
        if(totalPage == 0){
            pageBean.setTotalCount(0);
            pageBean.setTotalPage(0);
            return pageBean;
        }

        //若當前頁碼小於1,則設爲1
        if(currentPage < 1){
            currentPage =1;
        }
        //若當前頁面大於總頁數,則設爲總頁數
        if(currentPage > totalPage){
            currentPage = totalPage;
        }

        //調用dao層查詢要顯示的用戶到集合中
        int start = (currentPage-1) * rows;
        List<User> list = userDao.findUserByPage(start, rows, condition);

        //封裝PageBean對象
        pageBean.setTotalCount(totalCount);
        pageBean.setTotalPage(totalPage);
        pageBean.setRows(rows);
        pageBean.setCurrentPage(currentPage);
        pageBean.setList(list);
        return pageBean;

    }
  • 此方法中有兩處修改:一個是調用dao層查詢用戶記錄總條數方法,另一個是調用dao層查詢要顯示的用戶數據方法;在兩個方法中均加入了查詢的條件
    • 首先先來看看查詢用戶數據總條數方法
    
    public int findTotalCount(Map<String, String[]> condition) {

        //定義初始sql
        String sql = "select count(*) from user where 1 = 1 ";
        StringBuffer sb = new StringBuffer(sql);

        //遍歷map
        Set<String> keyset = condition.keySet();
        //定義用戶參數集合
        List<Object> params = new ArrayList<Object>();
        for (String key : keyset){

            //排除分頁的條件參數
            if(key.equals("currentPage") || key.equals("rows")){
                continue;
            }

            //獲取value
            String value = condition.get(key)[0];
            //判斷是否有值
            if(value != null && !"".equals(value)){

                sb.append(" and " + key + " like ?");
                params.add("%"+value+"%");
            }
        }
        sql = sb.toString();
        System.out.println(sql);
        System.out.println(params);

        return template.queryForObject(sql, Integer.class, params.toArray());
    }
  • 接下來再看看查詢用戶數據方法
    public List<User> findUserByPage(int start, int rows, Map<String, String[]> condition) {

        //定義初始sql
        String sql = "select * from user where 1 = 1 ";
        StringBuffer sb = new StringBuffer(sql);

        //遍歷map
        Set<String> keyset = condition.keySet();
        //定義用戶參數集合
        List<Object> params = new ArrayList<Object>();
        for (String key : keyset){

            //排除分頁的條件參數
            if(key.equals("currentPage") || key.equals("rows")){
                continue;
            }

            // 獲取value
            String value = condition.get(key)[0];
            //判斷是否有值
            if(value != null && !"".equals(value)){

                sb.append(" and " + key + " like ?");
                params.add("%"+value+"%");
            }
        }

        //添加分頁限制
        sb.append(" limit ?, ?");
        // 添加分頁查詢參數
        params.add(start);
        params.add(rows);
        sql = sb.toString();

        System.out.println(sql);
        System.out.println(params);

        return template.query(sql, new BeanPropertyRowMapper<User>(User.class), params.toArray());
    }
  • 最後細節的調整:在查詢狀態下,點擊分頁則不能回顯查詢數據,只需要在分頁按鈕處的href後添加查詢的請求參數即可,查詢的請求參數已經保存在request域中了;最後分頁處的代碼修改爲
    <div>
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <c:if test="${pageBean.currentPage == 1}">
                        <li class="disabled">
                    </c:if>
                    <c:if test="${pageBean.currentPage != 1}">
                        <li>
                    </c:if>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pageBean.currentPage - 1}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
                <c:forEach begin="1" end="${pageBean.totalPage}" var="i">

                    <c:if test="${pageBean.currentPage == i}">
                        <li class="active"><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${i}</a></li>
                    </c:if>

                    <c:if test="${pageBean.currentPage != i}">
                        <li><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${i}</a></li>
                    </c:if>
                </c:forEach>


                <li>
                    <c:if test="${pageBean.currentPage == pageBean.totalPage}">
                        <li class="disabled">
                    </c:if>
                    <c:if test="${pageBean.currentPage != pageBean.totalPage}">
                        <li>
                    </c:if>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pageBean.currentPage + 1}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
                <span style="font-size: 25px; margin: 8px">
                    共${pageBean.totalCount}條記錄,共${pageBean.totalPage}</span>
            </ul>
        </nav>
    </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章