springboot 入門教程(5) 基於ssm框架的crud操作(前端部分-附原始碼)
上一篇介紹了spring boot整合mybatis實現了後端的CRUD的查詢部分,本文主要是完善修改、刪除和新增操作的後端,實現前端頁面的呼叫。原始碼連結
https://pan.baidu.com/s/1c1DVwsw?errno=0&errmsg=Auth%20Login%20Sucess&&bduss=&ssnerror=0
(上一篇的原始碼有bug建議大家就看最新的)
1、完善新增、修改、刪除後臺
介面上篇已經定義號了,mapper也寫完了,接下來就是完善conntroller,並測試。直接上conntroller的程式碼吧,裡面註釋進行了說明。
這個版本里面加了分頁,service中的方法有的些變化,我也貼出來供大家參考,分頁的類在原始碼中有這裡就不貼了。
UserController.java
UserServiceImpl.java
2、整合前端Bootstap Table + jquery
前端其實很簡單,只有一個核心的html頁面和一個js,有很多細節這裡就不做過多介紹,比如表單中包括附件,處理方式肯定不同了哈。多選刪除我本來已經實現了,但是為了簡化又刪了。分頁是藉助了BootStrap分頁的引數(這個引數會自動帶到後臺,Bootstap table原始碼的引數和後臺我用PageInfo屬性名不一致,我改過Bootstap原始碼,目的就是為了不改pagehelper那個分頁外掛,也就是我選擇改前端來適應後端,就目前這個例子而言改前後都不會有影響。注意:直接在官網下載的BootStrap Table分頁和這個例子的後臺不能相容)
直接貼出html和js,懂點前端的朋友都能看懂,BootStrap Table不好理解的地方全部加了註釋,我的前端很爛的,寫得不好還請見諒了。
userList.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用者列表</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="stylesheet" type="text/css" href="../css/userList.css"> <link rel="stylesheet" type="text/css" href="../css/bootstrap/css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="../css/bootstrap-select.min.css"> <script type="text/javascript" src="../js/jquery-1.12.0.js"></script> <script type="text/javascript" src="../js/common.js"></script> <script type="text/javascript" src="../js/bootstrap-table.js"></script> <script type="text/javascript" src="../js/bootstrap-table-zh-CN.min.js"></script> <script type="text/javascript" src="../css/bootstrap/js/bootstrap.js"></script> <script type="text/javascript" src="js/userList.js"></script> </head> <body> <div class="container"> <div class="row"> <form class="form-horizontal" role="form"> <div class="from-group"> <div class="col-sm-1"> <input type="button" class="btn btn-primary" value="新增" /> </div> </div> </form> </div> <div class=""> <table id="mytab" class="table table-hover"></table> </div> </div> <!-- 編輯使用者資訊 模態視窗--> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title" id="myModalLabel">修改使用者資訊</h4> </div> <div class="modal-body"> <input type="hidden" id="sid" name="sid" /> <div class="form-group"> <label class="control-label">姓名:</label><input name="name" id="usernameTextE" type="text" class="form-control" /> </div> <div class="form-group"> <label class="control-label">性別:</label> <input id="gederTextM" value="M" name="gender" type="radio" /> 男 <input id="gederTextF" name="gender" value="F" type="radio" /> 女 </div> <div class="form-group"> <label class="control-label">年齡:</label><input name="age" id="ageTextE" type="text" class="form-control" /> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button> <button type="button" class="btn btn-primary" style="font-size: 13px;"> </div> </div> <!-- /.modal-content --> </div> <!-- /.modal-dialog --> </div> <!-- /.modal --> </body> </html>
userList.js
var myrow = {};
$(function() {
$('#mytab').bootstrapTable({
url : "../user/findUserByPage",// 資料來源
dataField : "list",// 服務端返回資料鍵值 就是說記錄放的鍵值是rows,分頁時使用總記錄數的鍵值為total
// search: true,//是否搜尋
totalField : "total",// 接收總頁數的引數
pagination : true,// 是否分頁
pageSize : 5,// 單頁記錄數
pageList : [ 5, 10, 20, 50 ],// 分頁步進值
sidePagination : "server",// 服務端分頁
// contentType: "application/x-www-form-urlencoded",//請求資料內容格式 預設是
// application/json 自己根據格式自行服務端處理
dataType : "json",// 期待返回資料型別
method : "get",// 請求方式
searchAlign : "left",// 查詢框對齊方式
queryParamsType : "other",// 查詢引數組織方式 為limit時候傳的引數是 offset和limit,否則為
// pageSize和pageNumber
// 可以帶查詢引數
// queryParams : function getParams(params) {
// params.name = $('#usernameText').val();
// return params;
// },
searchOnEnterKey : false,// 回車搜尋
columns : [
// {
// title : "全選",
// // field : "select",
// checkbox : true,
// width : 20,// 寬度
// align : "center",// 水平
// valign : "middle"// 垂直
// },
{
title : "使用者名稱",// 標題
field : "name"// 鍵名
// sortable: true,//是否可排序
// order: "desc"//預設排序方式
}, {
field : "gender",
title : "性別",
formatter : function(value, row, index) {
if (value == "F") {
return "女";
} else {
return "男";
}
}
},{
title : "註冊時間",// 標題
field : "regestDate"// 鍵名
}, {
title : "操作",
field : "control",
width : 70,
align : "center",
valign : "middle",
formatter : operateFormatter,
events : "operateEvents"
} ],
locale : "zh-CN", // 中文支援,
detailView : false
// 是否顯示詳情摺疊
});
});
window.operateEvents = {
'click .remove' : function(e, value, row) {
deleteSudentsById(row.id);
},
'click .edite' : function(e, value, row) {
$("#myModal").modal('show');
$("#sid").val(row.id);
// 為輸入框賦值
$("#usernameTextE").val(row.name);
$("#ageTextE").val(row.age);
$("#regestDateE").val(row.regestDate);
row.gender == "F" ? $("#gederTextF").prop("checked", "checked") : $(
"#gederTextM").prop("checked", "checked");
}
};
function operateFormatter(value, row, index) {
return [
'<div class="pull-center">',
'<a class="edite" href="javascript:void(0)" title="編輯" href="#"><span class="glyphicon glyphicon-expand"></span></a>',
' <a class="remove" href="javascript:void(0)" title="刪除">',
'<i class="glyphicon glyphicon-remove"></i>', '</a>', '</div>' ]
.join('');
}
// 新增使用者
function addUser() {
$("#sid").val("");
// 情況資訊編輯視窗(編輯和新增公用了一個視窗需要清空)
$("#usernameTextE").val("");
$("#gederTextM").attr("checked", "checked");// 性別預設為男
$("#dd").html("");// 清空頭像
// 彈出資訊編輯模態視窗
$("#myModal").modal('show');
}
// 儲存使用者資訊
function saveUser() {
// 呼叫後臺方法進行儲存
$.ajax({
url : '../user/addUser',
type : 'POST',
data : {
id : $("#sid").val(),
// 為輸入框賦值
name : $("#usernameTextE").val(),
age : $("#ageTextE").val(),
gender : $('#gederTextM:checked').val()
},
async : false,
cache : false,
success : function(returndata) {
// 關閉模態視窗
$("#myModal").modal('hide');
// 重新整理列表
$('#mytab').bootstrapTable('refresh');
},
error : function(returndata) {
alert("新增失敗!");
},
dataType : "json"
});
}
function deleteSudentsById(id) {
var r = confirm("確認要刪除該資料嗎!");
if (r == true) {
$.get("../user/deleteUser", {
id : id
}, function(data) {
alert("刪除成功!");
// 重新整理列表
$('#mytab').bootstrapTable('refresh');
}, "json");
} else {
alert("刪除失敗!")
}
}
// 下面用於多圖片上傳預覽功能
function setImagePreviews(avalue) {
var docObj = document.getElementById("upload-file");
var dd = document.getElementById("dd");
dd.innerHTML = "";
var fileList = docObj.files;
for (var i = 0; i < fileList.length; i++) {
dd.innerHTML += "<img id='img" + i + "' />";
var imgObjPreview = document.getElementById("img" + i);
if (docObj.files && docObj.files[i]) {
// 火狐下,直接設img屬性
imgObjPreview.style.display = 'block';
imgObjPreview.style.width = '150px';
imgObjPreview.style.height = '180px';
// imgObjPreview.src = docObj.files[0].getAsDataURL();
// 火狐7以上版本不能用上面的getAsDataURL()方式獲取,需要一下方式
imgObjPreview.src = window.URL.createObjectURL(docObj.files[i]);
} else {
// IE下,使用濾鏡
docObj.select();
var imgSrc = document.selection.createRange().text;
alert(imgSrc)
var localImagId = document.getElementById("img" + i);
// 必須設定初始大小
localImagId.style.width = "150px";
localImagId.style.height = "180px";
// 圖片異常的捕捉,防止使用者修改後綴來偽造圖片
try {
localImagId.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
localImagId.filters
.item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc;
} catch (e) {
alert("您上傳的圖片格式不正確,請重新選擇!");
return false;
}
imgObjPreview.style.display = 'none';
document.selection.empty();
}
}
return true;
}
總結:
其實這個demo前端大家可能會陌生一些,如果大家不習慣用BootStrap Table那就隨便換,後臺都實現了而且是rest介面 前端隨便你怎麼換,引數給對了就行了。
坑:
1、遇到亂碼問題,如果是資料傳到後臺沒亂碼,那一定就是資料庫的問題,設定下資料庫服務端編碼搞定,如果是前端傳到後端出現亂碼,那springboot 提供了直接在application.properties中設定編碼(參見原始碼)
2、實體屬性和資料庫屬性對應不上的時候要注意了,比如資料庫用的下劃線隔開,實體類中用的駝峰。
3、日期的格式,spring mvc rest方式介面會自動轉json格式返回,但是如果是日期格式預設直接轉換成毫秒,需要在實體屬性上加上註解@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")。
4、mybatis語法上的一些細節,這個只能靠多用多練了。
一個完整專案要用到的技術點太多,這只是個demo有很多細節沒有做處理(異常處理、單元測試、返回結果封裝、資料加密、介面許可權等等,太多了就不一一列舉了,以後有機會用專題文章來介紹)