尚籌網02管理員維護
阿新 • • 發佈:2020-07-19
任務清單
- 分頁顯示Admin資料
- 不帶關鍵詞分頁
- 帶關鍵詞分頁
- 新增Admin
- 更新Admin
- 單挑刪除Admin
分頁
目標
以分頁的形式把管理員資訊顯示到頁面上.
特殊需求:兼顧關鍵詞查詢,讓後端程式碼不管有沒有查詢條件都能夠以分頁形式顯示資料.
思路
- 點選使用者維護
- 跳轉到admin-page.jsp,在頁面初始化的時候把分頁資料也加載出來
- 在page頁面查詢關鍵詞的時候,提交給後臺,然後在頁面初始化的時候把分頁資料加載出來
- 點選上一頁下一頁,把頁面pageNum(和keyword)提交給後臺,然後在頁面初始化的時候把分頁資料加載出來
技術點
- 讓SQL語句針對
- 使用SQL中做字串連線的函式:CONCAT(“%”,#{keyword},”%”)
- keyword有值:“like %tom%“
- Key無值:”like %%“
- pageHelper使用
- 引入依賴
- 在SqlSessionFactoryBean中配置PageHelper
- 在Java程式碼中使用
- PageHelper.startPage(PageNum,PageSize)
- PageInfo<Admin> pageInfo = new PageInfo(adminList);
- 顯示頁碼
- 使用JQuery外掛:Pagination
後端程式碼
查詢Admin資料的SQL語句
<select id= "selectAdminByKeyword" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from t_admin where login_acct like CONCAT("%",#{keyword},"%") or user_name like CONCAT("%",#{keyword},"%") or email like CONCAT("%",#{keyword},"%")</select>
準備PageHelper環境
1、匯入座標
<!--mybatis 分頁外掛--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.11</version> </dependency>
2、配置SqlSessionFactoryBean
<!-- 配置 MyBatis 的外掛 --> <property name="plugins"> <array> <!-- 配置 PageHelper --> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> <!-- 分頁外掛會自動檢測當前的資料庫連結,自動選擇合適的分頁方式。 你可以配置helperDialect屬性來指定分頁外掛使用哪種方言。配置時,可以使用下面的縮寫值: oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby 特別注意:使用 SqlServer2012 資料庫時,需要手動指定為 sqlserver2012,否則會使用 SqlServer2005 的方式進行分頁。 --> helperDialect=mysql <!-- 預設false禁用 啟用合理化時,如果pageNum<1會查詢第一頁, 如果pageNum>pages會查詢最後一頁 禁用合理化時,如果pageNum<1或pageNum>pages會返回空資料 --> reasonable=true <!-- 支援通過 Mapper 介面引數來傳遞分頁引數,預設值false,分頁外掛會從查詢方法的引數值中,自動根據上面 params 配置的欄位中取值,查詢到合適的值時就會自動分頁。 使用方法可以參考測試程式碼中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和 ArgumentsObjTest。 --> supportMethodsArguments=true <!-- 為了支援startPage(Object params)方法,增加了該引數來配置引數對映, 用於從物件中根據屬性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置對映的用預設值, 預設值為pageNum=pageNum;pageSize=pageSize;count=countSql; reasonable=reasonable;pageSizeZero=pageSizeZero。 --> params=count=countSql <!-- 預設值為 false。設定為 true 時,允許在執行時根據多資料來源自動識別對應方言的分頁 (不支援自動選擇sqlserver2012,只能使用sqlserver)。 --> autoRuntimeDialect=true </value> </property> </bean> </array> </property>
3、AdminService方法
@Override public PageInfo<Admin> selectAdminByKeyWord(String keyWord, Integer pageNum, Integer pageSize) { // 1. 開啟pageHelper的靜態方法,開啟分頁功能 PageHelper.startPage(pageNum,pageSize); // 2. 執行查詢 List<Admin> admins = adminMapper.selectAdminByKeyWord(keyWord); // 3. 封裝到pageInfo物件中 PageInfo<Admin> pageInfo = PageInfo.of(admins); return pageInfo; }
4、AdminController
@RequestMapping("/admin/get/page.html") public String getPageInfo( //注意:頁面上有可能不提供關鍵詞,要進行匹配 //@RequestParam註解中設定defaultValue屬性為空字串表示不提供關鍵詞 @RequestParam(value = "keyword", defaultValue = "") String keyword, //預設從第一頁開始 @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, @RequestParam(value = "pageSize", defaultValue = "2") Integer pageSize, ModelMap modelMap) { // 1. 獲取pageInfo PageInfo<Admin> adminPageInfo = adminService.selectAdminByKeyWord(keyword, pageNum, pageSize); // 2. 將pageInfo存入Model modelMap.addAttribute(ConstantUtil.ATTR_NAME_PAGEINFO, adminPageInfo); return "/admin-page"; }
5、前端程式碼
根據返回的pageInfo資料,拼接成表進行顯示
<tbody> <c:if test="${empty requestScope.pageInfo.list}"> <tr> <td colspan="6" align="center"> 抱歉!沒有查詢到你要的資料</td> </tr> </c:if> <c:if test="${!empty requestScope.pageInfo.list}"> <c:forEach items="${requestScope.pageInfo.list}" var="admin" varStatus="myStatus"> <tr> <td>${myStatus.count}</td> <td><input type="checkbox"></td> <td>${admin.loginAcct}</td> <td>${admin.userName}</td> <td>${admin.email}</td> <td> <%--<button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>--%> <a href="assign/to/assign/role/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></a> <%--<button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>--%> <%--<button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>--%> <a href="admin/to/edit/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></a> <a href="admin/remove/${admin.id}/${requestScope.pageInfo.pageNum}/${param.keyword}.html" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></a> </td> </tr> </c:forEach> </c:if> </tbody>
6、加入Pagination外掛環境
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html lang="zh_CN"> <%@include file="/WEB-INF/pages/admincommon/include-head.jsp" %> <link rel="stylesheet" href="static/css/pagination.css"/> <script type="text/javascript" src="static/jquery/jquery.pagination.js"></script> <script type="text/javascript">
7、編寫pagination程式碼
<script type="text/javascript">
$(function () { initPagination(); }); //生成分頁導航條函式 function initPagination() { //獲取總記錄數 var totalRecord = ${requestScope.pageInfo.total}; var properties = { num_edge_entries: 3, //邊緣頁數 num_display_entries: 5, //主體頁數 callback: pageselectCallback, items_per_page:${requestScope.pageInfo.pageSize}, //每頁顯示1項 current_page: ${requestScope.pageInfo.pageNum - 1},//Pagination內部使用pageIndex來管理頁面 prev_text: "上一頁", next_text: "下一頁" } // 生成頁碼導航條 $("#Pagination").pagination(totalRecord, properties); } //pageIndex 0- function pageselectCallback(pageIndex, jQuery) { //根據pageIndex計算pageNum var pageNum = pageIndex + 1; //跳轉頁面 window.location.href = "admin/get/page.html?pageNum=" + pageNum + "&keyword=${param.keyword}"; //由於每個按鈕都是超連結,所以這裡取消超連結的預設行為
//由於會回撥函式,且我們這裡時跳轉頁面,因此會不斷重複
//解決方法是return false取消預設回撥的行為
return false } </script>
關鍵詞查詢
頁面調整待提交的表單
<form action="admin/get/page.html" method="post" class="form-inline" role="form" style="float:left;"> <div class="form-group has-feedback"> <div class="input-group"> <div class="input-group-addon">查詢條件</div> <input name="keyword" class="form-control has-success" type="text" placeholder="請輸入查詢條件"> </div> </div> <button type="submit" class="btn btn-warning"><i class="glyphicon glyphicon-search"></i> 查詢 </button> </form>
翻頁時保持keyword值
//pageIndex 0- function pageselectCallback(pageIndex, jQuery) { //根據pageIndex計算pageNum var pageNum = pageIndex + 1; //跳轉頁面 //EL表示式中的param也是一個隱含物件,可以用來獲取請求引數 window.location.href = "admin/get/page.html?pageNum=" + pageNum + "&keyword=${param.keyword}"; //由於每個按鈕都是超連結,所以這裡取消超連結的預設行為 return false; }
注意:EL表示式中的param是一個隱含的物件,可以用來獲取請求引數.
新增管理員資訊
目標
建立新的管理員資訊,通過表單
思路
程式碼
設定唯一約束
Alter table ‘表名’ add unique index(‘欄位名’)
業務層邏輯
@Override public void saveAdmin(Admin admin) { //生成系統當前時間 Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String createTime = format.format(date); admin.setCreateTime(createTime); //針對登陸密碼進行加密 String source = admin.getUserPswd(); String encoded = MD5Util.md5(source); admin.setUserPswd(encoded); //執行儲存,如果賬號被佔用會丟擲異常 try{ adminMapper.insert(admin); }catch(Exception e){ e.printStackTrace(); //檢測當前捕獲的異常物件,如果是DuplicateKeyException型別說明賬號重複導致 if (e instanceof DuplicateKeyException){ //丟擲自定義的LoginAcctAlreadyExist throw new LoginAccountAlreadlyInUse(ConstantUtil.MESSAGE_SYSTEM_ERROR_LOGIN_NOT_UNIQUE); } //如果不是則繼續往上拋 throw e; } }
異常對映處理器類
當丟擲對應異常時,會被異常攔截器捕捉
@ExceptionHandler(LoginAccountAlreadlyInUse.class) public ModelAndView resolverLoginAccountAlreadlyInUseException(LoginAccountAlreadlyInUse e, HttpServletRequest request, HttpServletResponse response) throws IOException { String viewName = "admin-add"; ModelAndView modelAndView = common(viewName, e, request, response); return modelAndView; } /** * 提取可複用部分 * @return */ public ModelAndView common(String viewName, Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException { boolean requestType = CrowdUtil.isAjaxRequest(request); if (requestType) { ResultEntity<Object> failed = ResultEntity.failed(e.getMessage()); String json = new Gson().toJson(failed); response.getWriter().write(json); return null; } else { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("exception", e); modelAndView.setViewName(viewName); return modelAndView; } }
自定義異常
控制層
@RequestMapping("/save/admin.html") public String saveAdmin(Admin admin) { //執行儲存 adminService.saveAdmin(admin); // 為了讓使用者第一眼就看到新增加的使用者,直接跳轉到最後一頁 return "redirect:/admin/page.html?pageNum=" + Integer.MAX_VALUE; }
儲存之後重定向
"redirect:/admin/page.html?pageNum=" + Integer.MAX_VALUE;
表單頁面
配置跳轉
<mvc:view-controller path="/admin/to/add/page.html" view-name="admin-add"/>
更新刪除管理員資訊
目標
通過提交頁面上的表單修改某個Admin的資料
思路
- 在admin-page.jsp頁面點選修改,帶著id到後臺,查詢出對應的admin
- 把admin儲存在request域
- 重定向到edit頁面並填充
- 當點選修改時到後臺執行更新
- 重定向到page頁面
- 為了保持所在頁和關鍵詞還需要pageNum和keyword
- 重定向到main-page.jsp點選刪除(攜帶id)
- 提交到後臺處理完,重定向到page頁面
- 什麼時候使用重定向,不需要再返回操作,不需要request的資料
程式碼
<a href="admin/to/edit/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></a> <a href="admin/remove/${admin.id}/${requestScope.pageInfo.pageNum}/${param.keyword}.html" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></a>
controller
@RequestMapping("/admin/to/edit/page.html") public String toAdminEdit(@RequestParam("adminId") Integer adminId, ModelMap map) { // 1.根據 id(主鍵)查詢待更新的 Admin 物件 Admin admin = adminService.selectAdminById(adminId); // 2.將 Admin 物件存入模型 map.addAttribute("admin", admin); return "admin-edit"; } // @RequestMapping("/admin/update.html") public String editAdmin(Admin admin, @RequestParam("pageNum") Integer pageNum, @RequestParam("keyword") String keyword, ModelMap map) { adminService.updateAdmin(admin); return "redirect:/admin/get/page.html?pageNum=" + pageNum + "&keyword=" + keyword; }
@RequestMapping("/admin/remove/{id}/{pageNum}/{keyword}") public String deleteAdmin(@PathVariable("id") Integer id, @PathVariable("pageNum") Integer pageNum, @PathVariable(value = "keyword") String keyword) { adminService.deleteAdminByPrimaryKey(id); return "redirect:/admin/get/page.html?pageNum=" + pageNum + "&keyword=" + keyword; }
service
@Override public void deleteAdminByPrimaryKey(Integer id) { adminMapper.deleteByPrimaryKey(id); } @Override public Admin selectAdminById(Integer adminId) { Admin admin = adminMapper.selectByPrimaryKey(adminId); return admin; } @Override public void updateAdmin(Admin admin) { try { adminMapper.updateByPrimaryKeySelective(admin); } catch (Exception e) { if (e instanceof DuplicateKeyException) { throw new LoginAccountAlreadlyInUseForUpdate("不允許重複的賬戶"); } } }