綜合練習筆記(用戶管理系統)
1. 結合上次用戶信息列表展示案例進行簡單修改
* 列表查詢
* 登錄
* 添加
* 刪除
* 修改
2. 增加更多複雜的功能
* 刪除選中
* 分頁查詢
* 複雜條件查詢
複雜的功能
- 刪除選中
- 選中功能指的是複選框,複選框的提交方式是多個請求參數的形式:?id=1&id=2&id=3&id=4等;
- *批量刪除功能的實現流程如圖所示
- 請求參數提交成功後,需要再web層加一個Servlet進行處理,記爲DelSelectedServlet
- DelSelectedServlet的主要步驟:
- 獲取請求參數數組
- 調用service層中的刪除多個用戶方法
- 跳轉到頁面展示
- service層中的批量刪除方法只需要在dao層刪除一個用戶的基礎上多次調用即可
- 先將後臺的程序完成如下,在此之前也需要將複選框的name記爲uid,value記爲用戶的id
- DelSelectedServlet的主要步驟:
//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">«</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">»</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">«</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">»</span>
</a>
</li>
<span style="font-size: 25px; margin: 8px">
共${pageBean.totalCount}條記錄,共${pageBean.totalPage}頁
</span>
</ul>
</nav>
</div>