1. 用戶維護(hù)-單條刪除
1.1 給單條刪除按鈕綁定單擊響應(yīng)函數(shù)
使用class屬性標(biāo)記多個元素拗盒。admin-page.jsp
<button adminId="${admin.id }" type="button" class="btn btn-danger btn-xs uniqueRemoveBtn">
<i class=" glyphicon glyphicon-remove"></i>
</button>
給class為uniqueRemoveBtn的按鈕綁定單擊響應(yīng)函數(shù)
// 給單條刪除按鈕綁定單擊響應(yīng)函數(shù)
$(".uniqueRemoveBtn").click(function(){
// 獲取當(dāng)前adminId值
var adminId = $(this).attr("adminId");
// 獲取當(dāng)前記錄的loginAcct
var loginAcct = $(this).parents("tr").children("td:eq(2)").text();
var confirmResult = confirm("您真的要刪除"+loginAcct+"這條記錄嗎浩峡?");
if(!confirmResult) {
return ;
}
// 為了能夠使用批量刪除的操作,將adminId存入數(shù)組
var adminIdArray = new Array();
adminIdArray.push(adminId);
// 調(diào)用專門封裝的函數(shù)岸售,執(zhí)行批量刪除
doBatchRemove(adminIdArray);
});
1.2 專門封裝執(zhí)行批量刪除的函數(shù)
這個函數(shù)同時根據(jù)傳入的數(shù)組不同践樱,既可以批量刪除也可以單條刪除
// 封裝執(zhí)行批量刪除的函數(shù)
function doBatchRemove(adminIdArray) {
// 將JSON數(shù)組轉(zhuǎn)換為JSON字符串
// var a = [1,2,3,4,5]; 數(shù)組類型
// var b = "[1,2,3,4,5]"; 字符串類型
// var c = {"userName":"tom"}; 對象類型
// var d = "{\"userName\":\"tom\"}"; 字符串類型
// 發(fā)送Ajax請求執(zhí)行批量刪除
var requestBody = JSON.stringify(adminIdArray);
// 發(fā)送Ajax請求將adminIdArray發(fā)送給handler方法
$.ajax({
"url":"admin/batch/remove.json", // 服務(wù)器端接收請求的URL地址
"type":"post", // 設(shè)置請求方式為POST
"contentType":"application/json;charset=UTF-8", // 設(shè)置請求體內(nèi)容類型,告訴服務(wù)器當(dāng)前請求體發(fā)送的是JSON數(shù)據(jù)
"data":requestBody, // 請求體真正要發(fā)送給服務(wù)器的數(shù)據(jù)
"dataType":"json", // 把服務(wù)器端返回的數(shù)據(jù)當(dāng)作JSON格式解析
"success":function(response) { // 服務(wù)器處理請求成功后執(zhí)行的函數(shù)凸丸,響應(yīng)體以參數(shù)形式傳入當(dāng)前函數(shù)
console.log(response);
var result = response.result;
if(result == "SUCCESS") {
// 跳轉(zhuǎn)頁面
window.location.href = "admin/query/for/search.html?pageNum=${requestScope['PAGE-INFO'].pageNum}&keyword=${param.keyword}";
}
if(result == "FAILED") {
alert(response.message);
return ;
}
},
"error":function(response) { // 服務(wù)器處理請求失敗后執(zhí)行的函數(shù)拷邢,響應(yīng)體以參數(shù)形式傳入當(dāng)前函數(shù)
alert(response.message);
return ;
}
});
2. 將目前為止所有另外聲明的函數(shù)提取到外部JS文件中
2.1 創(chuàng)建JavaScript文件
- 所在工程:atcrowdfunding-admin-1-webui
- 文件位置:/atcrowdfunding-admin-1-webui/src/main/webapp/script/my-admin.js
2.2 原本EL表達(dá)式處理
EL表達(dá)式不能出現(xiàn)在JavaScript文件中,需要額外以參數(shù)形式傳入屎慢。
2.3 將pageNum和keyword放在全局變量范圍統(tǒng)一維護(hù)
目的:讓pageNum和keyword實(shí)現(xiàn)一處修改瞭稼,處處生效。需要使用pageNum和keyword值的操作直接從全局變量范圍讀取即可腻惠。
admin-page.jsp
$(function () {
// 初始化全局變量
window.totalRecord = ${requestScope['PAGE-INFO'].total};
window.pageSize = ${requestScope['PAGE-INFO'].pageSize};
window.pageNum = ${requestScope['PAGE-INFO'].pageNum};
// 每一次頁面最初顯示的時候都會把keyword設(shè)置為最新值
window.keyword = "${param.keyword}";
my-admin.js
//對分頁導(dǎo)航條顯示進(jìn)行初始化
function initPagination() {
//聲明變量存儲總記錄數(shù)
//var totalRecord = ${requestScope['PAGE-INFO'].total};
//聲明遍歷存儲分頁導(dǎo)航條顯示時的屬性設(shè)置
var paginationProperties = {
num_edge_entries: 3, //邊緣頁數(shù)
num_display_entries: 5, //主體頁數(shù)
callback: pageselectCallback,//回調(diào)函數(shù)
items_per_page: window.pageSize,//每頁顯示數(shù)據(jù)數(shù)量弛姜,就是pageSize
current_page:(window.pageNum-1),//當(dāng)前頁
prev_text:"上一頁",//上一頁文本
next_text:"下一頁"http://下一頁文本
}
// 顯示分頁的導(dǎo)航條
$("#Pagination").pagination(window.totalRecord, paginationProperties);
}
//在每一次點(diǎn)擊"上一頁","下一頁"妖枚,"頁碼"時執(zhí)行這個函數(shù)跳轉(zhuǎn)頁面
function pageselectCallback(pageIndex, jq) {
//pageIndex從0開始廷臼,pageNum從1開始
window.pageNum = pageIndex+1;
//跳轉(zhuǎn)頁面
window.location.href="admin/query/for/search.html?pageNum="+(pageIndex+1)+"&keyword="+window.keyword;
return false;
}
//封裝執(zhí)行批量刪除的函數(shù)
function doBatchRemove(adminIdArray) {
//發(fā)送ajax請求執(zhí)行批量刪除
var requestBody = JSON.stringify(adminIdArray);
//發(fā)送ajax請求將adminIdArray發(fā)送給handler方法
$.ajax({
"url":"admin/batch/remove.json",//服務(wù)端接收請求的URL地址
"type":"post",//設(shè)置請求方式為post
"contentType":"application/json;charset=UTF-8",//設(shè)置請求體內(nèi)容類型,告訴服務(wù)器發(fā)的是JSON數(shù)據(jù)
"data":requestBody,//請求體真正要發(fā)送的數(shù)據(jù)
"success":function (response) {//服務(wù)器處理請求成功后的函數(shù)绝页,響應(yīng)體以參數(shù)形式傳入當(dāng)前函數(shù)
console.log(response);
var result = response.result;
//跳轉(zhuǎn)頁面
if(result == "SUCCESS"){
window.location.href = "admin/query/for/search.html?pageNum="+window.pageNum+"&keyword="+window.keyword;
}
//
if(result == "FAILED"){
alert(response.message);
return;
}
},
"error":function (response) {
alert(response.message);
}
})
}
2.4 在JSP頁面上引入外部JavaScript文件
<script type="text/javascript" src="script/my-admin.js"></script>
注意:使用script標(biāo)簽引入外部JavaScript文件需要注意引入的順序荠商。
如果a.js文件中用到了b.js文件中的函數(shù),那么引入是順序應(yīng)該是:b前续誉,a后
3. 用戶維護(hù)-新增操作
3.1 給t_admin表的login_acct字段添加唯一約束
ALTER TABLE `t_admin`
ADD UNIQUE INDEX (`login_acct`)
3.2 流程分析
3.3 跳轉(zhuǎn)到新增表單頁面
3.3.1 把新增按鈕改成超鏈接
admin-page.jsp
修改前
<button type="button" class="btn btn-primary"style="float: right;" onclick="window.location.href='add.html'">
<i class="glyphicon glyphicon-plus"></i> 新增
</button>
修改后
<a href="admin/to/add/page.html" class="btn btn-primary" style="float: right;"><i class="glyphicon glyphicon-plus"></i> 新增</a>
3.3.2 view-controller配置
spring-web-mvc.xml
<mvc:view-controller path="/admin/to/add/page.html" view-name="admin-add"/>
3.3.3 創(chuàng)建admin-add.jsp
面包屑部分
<ol class="breadcrumb">
<li><a href="admin/to/main/page.html">首頁</a></li>
<li><a href="admin/query/for/search.html">數(shù)據(jù)列表</a></li>
<li class="active">新增</li>
</ol>
表單部分
<form action="admin/save.html" method="post" role="form">
<div class="form-group">
<label for="exampleInputPassword1">登錄賬號</label>
<input
type="text"
name="loginAcct"
class="form-control"
id="exampleInputPassword1"
placeholder="請輸入登陸賬號"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">登錄密碼</label>
<input
type="text"
name="userPswd"
class="form-control"
id="exampleInputPassword1"
placeholder="請輸入用戶名稱"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">用戶昵稱</label>
<input
type="text"
name="userName"
class="form-control"
id="exampleInputPassword1"
placeholder="請輸入用戶名稱"/>
</div>
<div class="form-group">
<label for="exampleInputEmail1">郵箱地址</label>
<input
type="email"
name="email"
class="form-control"
id="exampleInputEmail1"
placeholder="請輸入郵箱地址"/>
</div>
<button type="submit" class="btn btn-success">
<i class="glyphicon glyphicon-plus"></i> 新增
</button>
<button type="reset" class="btn btn-danger">
<i class="glyphicon glyphicon-refresh"></i> 重置
</button>
</form>
3.4 執(zhí)行保存操作
3.4.1 handler方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.handler.AdminHandler
// 使用Admin實(shí)體類對象封裝表單提交的請求參數(shù)莱没,具體每一個請求參數(shù)會通過對應(yīng)的setXxx()方法注入實(shí)體類
@RequestMapping("/admin/save")
public String saveAdmin(Admin admin) {
adminService.saveAdmin(admin);
return "redirect:/admin/query/for/search.html";
}
3.4.2 service方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.service.impl.AdminServiceImpl
@Override
public void saveAdmin(Admin admin) {
// 對密碼進(jìn)行加密
String userPswd = admin.getUserPswd();
userPswd = CrowdFundingUtils.md5(userPswd);
admin.setUserPswd(userPswd);
// 執(zhí)行保存
adminMapper.insert(admin);
}
3.4.3 轉(zhuǎn)換拋出的異常
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.handler.AdminHandler
// 使用Admin實(shí)體類對象封裝表單提交的請求參數(shù),具體每一個請求參數(shù)會通過對應(yīng)的setXxx()方法注入實(shí)體類
@RequestMapping("/admin/save")
public String saveAdmin(Admin admin) {
try {
adminService.saveAdmin(admin);
} catch (Exception e) {
e.printStackTrace();
if(e instanceof DuplicateKeyException) {
throw new RuntimeException(CrowdFundingConstant.MESSAGE_LOGIN_ACCT_ALREADY_IN_USE);
}
}
return "redirect:/admin/query/for/search.html";
}
3.5 操作完成后立即看到新增的記錄
3.5.1 方案一
跳轉(zhuǎn)到分頁頁面時前往最后一頁
return "redirect:/admin/query/for/search.html?pageNum="+Integer.MAX_VALUE;
3.5.2 方案二
分頁頁面顯示數(shù)據(jù)時根據(jù)id降序排列
<select id="selectAdminListByKeyword" 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}, "%")
order by id desc
</select>
4. 用戶維護(hù)-更新操作
4.1 操作流程
4.2 跳轉(zhuǎn)到更新頁面
4.2.1 把鉛筆按鈕改成超鏈接
修改前
<button type="button" class="btn btn-primary btn-xs">
<i class=" glyphicon glyphicon-pencil"></i>
</button>
修改后
<a href="admin/to/edit/page.html?adminId=${admin.id }&pageNum=${requestScope['PAGE-INFO'].pageNum}" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></a>
4.2.2 handler方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.handler.AdminHandler
@RequestMapping("/admin/to/edit/page")
public String toEditPage(@RequestParam("adminId") Integer adminId, Model model) {
Admin admin = adminService.getAdminById(adminId);
model.addAttribute("admin", admin);
return "admin-edit";
}
4.2.3 service方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.service.impl.AdminServiceImpl
@Override
public Admin getAdminById(Integer adminId) {
return adminMapper.selectByPrimaryKey(adminId);
}
4.2.4 創(chuàng)建admin-edit.jsp
引入spring的form標(biāo)簽
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<form:form action="admin/update.html" method="post" modelAttribute="admin">
<!-- 模型對象中包含的屬性可以使用form:hidden -->
<form:hidden path="id"/>
<!-- 模型對象中沒有的屬性不能使用form:hidden -->
<input type="hidden" name="pageNum" value="${param.pageNum }" />
<div class="form-group">
<label for="exampleInputPassword1">登錄賬號</label>
<form:input path="loginAcct" cssClass="form-control"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">登錄密碼</label>
<form:input path="userPswd" cssClass="form-control"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">用戶昵稱</label>
<form:input path="userName" cssClass="form-control"/>
</div>
<div class="form-group">
<label for="exampleInputEmail1">郵箱地址</label>
<form:input path="email" cssClass="form-control"/>
</div>
<button type="submit" class="btn btn-success">
<i class="glyphicon glyphicon-edit"></i> 更新
</button>
<button type="reset" class="btn btn-danger">
<i class="glyphicon glyphicon-refresh"></i> 重置
</button>
</form:form>
4.3 執(zhí)行更新
4.3.1 handler方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.handler.AdminHandler
@RequestMapping("/admin/update")
public String updateAdmin(Admin admin) {
try {
adminService.updateAdmin(admin);
} catch (Exception e) {
e.printStackTrace();
if(e instanceof DuplicateKeyException) {
throw new RuntimeException(CrowdFundingConstant.MESSAGE_LOGIN_ACCT_ALREADY_IN_USE);
}
}
return "redirect:/admin/query/for/search.html?pageNum="+pageNum;
}
4.3.2 service方法
- 工程目錄:atcrowdfunding-admin-2-component
- 全類名:com.rgh.crowd.funding.service.impl.AdminServiceImpl
@Override
public void updateAdmin(Admin admin) {
// 對密碼進(jìn)行加密
String userPswd = admin.getUserPswd();
userPswd = CrowdFundingUtils.md5(userPswd);
admin.setUserPswd(userPswd);
// 執(zhí)行更新
adminMapper.updateByPrimaryKey(admin);
}
5. HTTP協(xié)議復(fù)習(xí)
5.1 請求報文
5.1.1 請求行
Request URL: http://localhost:8080/atcrowdfunding-admin-1-webui/css/pagination.css
Request Method: GET
HTTP協(xié)議的版本酷鸦,通常是1.1
5.1.2 請求消息頭
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 132
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=DBC23B26C8603DE7985C3FEC2685859E
Host: localhost:8080
Origin: http://localhost:8080
Pragma: no-cache
Referer: http://localhost:8080/atcrowdfunding-admin-1-webui/admin/to/edit/page.html?adminId=484&pageNum=5
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Content-Type進(jìn)一步說明:
常用類型
-
application/x-www-form-urlencoded
通常是提交一個表單所產(chǎn)生的
-
application/json;charset=UTF-8
通常是發(fā)送Ajax請求饰躲,請求體整個是一個JSON數(shù)據(jù)
$.ajax({
"url":"admin/batch/remove.json", // 服務(wù)器端接收請求的URL地址
"type":"post", // 設(shè)置請求方式為POST
"contentType":"application/json;charset=UTF-8", // 設(shè)置請求體內(nèi)容類型牙咏,告訴服務(wù)器當(dāng)前請求體發(fā)送的是JSON數(shù)據(jù)
"data":JSON.stringify(adminIdArray), // 請求體真正要發(fā)送給服務(wù)器的數(shù)據(jù)
"dataType":"json", // 把服務(wù)器端返回的數(shù)據(jù)當(dāng)作JSON格式解析
"success":function(response) { // 服務(wù)器處理請求成功后執(zhí)行的函數(shù),響應(yīng)體以參數(shù)形式傳入當(dāng)前函數(shù)
console.log(response);
var result = response.result;
if(result == "SUCCESS") {
// 跳轉(zhuǎn)頁面
// window.location.href = "admin/query/for/search.html?pageNum="+window.pageNum+"&keyword="+window.keyword;
}
if(result == "FAILED") {
alert(response.message);
return ;
}
},
"error":function(response) { // 服務(wù)器處理請求失敗后執(zhí)行的函數(shù)嘹裂,響應(yīng)體以參數(shù)形式傳入當(dāng)前函數(shù)
alert(response.message);
return ;
}
});
這樣提交的請求妄壶,handler方法接收數(shù)據(jù)需要使用@RequestBody注解
@ResponseBody
@RequestMapping("/admin/batch/remove")
public ResultEntity<String> batchRemove(@RequestBody List<Integer> adminIdList) {
try {
adminService.batchRemove(adminIdList);
return ResultEntity.successWithoutData();
}catch(Exception e) {
return ResultEntity.failed(null, e.getMessage());
}
}
-
multipart/form-data
用于文件上傳
<form action="xxx" method="post" enctype="multipart/form-data"
5.1.3 請求體
請求體當(dāng)前請求要發(fā)送給服務(wù)器的數(shù)據(jù)主體,GET方式?jīng)]有請求體寄狼,POST方式有請求體丁寄。
傳送較大數(shù)據(jù)量時使用POST方式。
5.2 響應(yīng)報文
5.2.1 響應(yīng)狀態(tài)行
Status Code: 200 OK
- 200表示請求處理成功
- 302表示重定向
- 404表示找不到目標(biāo)資源
- 50X表示服務(wù)器內(nèi)部錯誤
5.2.2 響應(yīng)消息頭
Content-Type: application/json;charset=UTF-8
Set-Cookie: JSESSIONID=104DED3F5A868930A70834DEC585983B; Path=/atcrowdfunding-admin-1-webui/; HttpOnly
5.2.3 響應(yīng)體
-
常見形式1:頁面
通常用來響應(yīng)“同步請求”
-
常見形式2:JSON數(shù)據(jù)
通常用來響應(yīng)“異步請求”
6. 同步請求和異步請求
6.1 同步請求
同一個線程內(nèi)部泊愧,后面操作需要等前面操作完成才能開始伊磺。
6.2 異步請求
兩個或多個操作在各自線程里執(zhí)行,互不干擾删咱,并行推進(jìn)屑埋。