尚籌網(wǎng)-6.Role維護(hù)和異步請(qǐng)求的異常映射

1 html和json擴(kuò)展名問題

1.1 對(duì)應(yīng)*.html擴(kuò)展名的請(qǐng)求

返回一個(gè)完整頁(yè)面的請(qǐng)求。

1.2 對(duì)應(yīng)*.json擴(kuò)展名的請(qǐng)求

返回JSON數(shù)據(jù)的請(qǐng)求。

{"result":"SUCCESS","message":"NO_MESSAGE","data":
{"pageNum":2,"pageSize":5,"size":5,"startRow":6,"endRow":10,"total":100,"pages":20,"list":
[{"id":6,"name":"role5"},{"id":7,"name":"role6"},{"id":8,"name":"role7"},{"id":9,"name":"role8"},
{"id":10,"name":"role9"}],"firstPage":1,"prePage":1,"nextPage":3,"lastPage":8,"isFirstPage":false,
"isLastPage":false,"hasPreviousPage":true,"hasNextPage":true,"navigatePages":8,"navigatepageNums":
[1,2,3,4,5,6,7,8]}}

1.3 匹配錯(cuò)誤時(shí)的問題

如果請(qǐng)求擴(kuò)展名是*.html,但是實(shí)際返回的響應(yīng)體是JSON格式,Tomcat會(huì)認(rèn)為實(shí)際返回的響應(yīng)和響應(yīng)消息頭中的內(nèi)容類型不匹配,會(huì)拋異常。

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

此時(shí)要解決這個(gè)問題,將返回JSON數(shù)據(jù)的請(qǐng)求擴(kuò)展名設(shè)置為*.json或Tomcat無法識(shí)別的擴(kuò)展名即可。

例如:xxx.json或xxx.rgh都可以。

2. 角色維護(hù)-關(guān)鍵詞查詢功能

2.1 基本思路

在點(diǎn)擊“查詢”按鈕后,獲取文本框中填寫的keyword值,賦值給全局變量keyword,調(diào)用showPage()函數(shù)即可。

  • 給“查詢”按鈕標(biāo)記id
  • 給“查詢”按鈕綁定單擊響應(yīng)函數(shù)
  • 在單擊響應(yīng)函數(shù)中獲取文本框中輸入的數(shù)據(jù)
  • 驗(yàn)證輸入數(shù)據(jù)是否有效
    • 如果無效,提示,停止函數(shù)執(zhí)行
    • 如果有效,賦值給window.keyword
  • 調(diào)用showPage()

2.2 代碼

$("#searchBtn").click(function(){
    // 在單擊響應(yīng)函數(shù)中獲取文本框中輸入的數(shù)據(jù)
    var keyword = $.trim($("#keywordInput").val());
    // 驗(yàn)證輸入數(shù)據(jù)是否有效
    if(keyword == null || keyword == "") {
        // 如果無效,提示,停止函數(shù)執(zhí)行
        layer.msg("請(qǐng)輸入關(guān)鍵詞!");
        return ;
    }
    // 如果有效,賦值給window.keyword
    window.keyword = keyword;
    // 調(diào)用showPage()重新分頁(yè)
    showPage();
});

layer.msg('xxx')無法顯示的原因

3 角色維護(hù)-全選功能

3.1 功能在頁(yè)面的位置

3.2 具體實(shí)現(xiàn)

3.2.1 標(biāo)記

總checkbox:/atcrowdfunding-admin-1-webui/src/main/webapp/WEB-INF/role-page.jsp

<thead>
    <tr>
        <th width="30">#</th>
        <th width="30"><input id="summaryBox" type="checkbox"></th>
        <th>名稱</th>
        <th width="100">操作</th>
    </tr>
</thead>

itembox:/atcrowdfunding-admin-1-webui/src/main/webapp/script/my-role.js

// 使用PageInfo數(shù)據(jù)在tbody標(biāo)簽內(nèi)顯示分頁(yè)數(shù)據(jù)
function generateTableBody(pageInfo) {
    ……
    for(var i = 0; i < list.length; i++) {
        ……
        var checkBoxTd = "<td><input roleid='"+role.id+"' class='itemBox' type='checkbox'></td>";
        ……
    }
}

3.2.2 給#summaryBox綁定單擊響應(yīng)函數(shù)

// 全選/全不選功能
$("#summaryBox").click(function(){
    // 1.獲取當(dāng)前checkbox的選中狀態(tài)
    var currentStatus = this.checked;
    // 2.設(shè)置itemBox的選中狀態(tài)
    $(".itemBox").prop("checked",currentStatus);
});

4. 角色維護(hù)-批量刪除

4.1 準(zhǔn)備工作

4.1.1 準(zhǔn)備模態(tài)框

<div id="confirmModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"
                        aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title">尚籌網(wǎng)系統(tǒng)彈窗</h4>
            </div>
            <div class="modal-body">
                <p>您確定要?jiǎng)h除下面的顯示的內(nèi)容嗎?</p>
                <table class="table table-bordered">
                    <thead>
                        <tr>
                            <th width="30">#</th>
                            <th>名稱</th>
                        </tr>
                    </thead>
                    <tbody id="confirmModalTableBody"></tbody>
                </table>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary">OK</button>
            </div>
        </div>
    </div>
</div>

創(chuàng)建include-modal-role-confirm.jsp文件保存模態(tài)框內(nèi)容。

在role-page.jsp中包含include-modal-role-confirm.jsp文件。

    ……
    <%@ include file="/WEB-INF/include-modal-role-confirm.jsp" %>
</body>

4.1.2 getRoleListByRoleIdArray()函數(shù)

// 根據(jù)roleIdArray查詢r(jià)oleList
function getRoleListByRoleIdArray(roleIdArray) {
    // 1.將roleIdArray轉(zhuǎn)換成JSON字符串
    var requestBody = JSON.stringify(roleIdArray);  
    // 2.發(fā)送Ajax請(qǐng)求
    var ajaxResult = $.ajax({
        "url":"role/get/list/by/id/list.json",
        "type":"post",
        "data":requestBody,
        "contentType":"application/json;charset=UTF-8",
        "dataType":"json",
        "async":false
    });
    // 3.獲取JSON對(duì)象類型的響應(yīng)體
    var resultEntity = ajaxResult.responseJSON;
    // 4.驗(yàn)證是否成功
    var result = resultEntity.result;
    if(result == "SUCCESS") {   
        // 5.如果成功,則返回roleList
        return resultEntity.data;
    }
    if(result == "FAILED") {
        layer.msg(resultEntity.message);
        return null;
    }
    return null;    
}

對(duì)應(yīng)的后端代碼:

com.rgh.crowd.funding.handler.RoleHandler

// handler方法
@ResponseBody
@RequestMapping("/role/get/list/by/id/list")
public ResultEntity<List<Role>> getRoleListByIdList(@RequestBody List<Integer> roleIdList) {
    List<Role> roleList = roleService.getRoleListByIdList(roleIdList);  
    return ResultEntity.successWithData(roleList);
}

com.rgh.crowd.funding.service.impl.RoleServiceImpl

// service方法
@Override
public List<Role> getRoleListByIdList(List<Integer> roleIdList) {
    // 預(yù)期的SQL語句
    // select id,name from t_role where id in (1,2,3,6,12)
    // 創(chuàng)建實(shí)體類Role對(duì)應(yīng)的Example對(duì)象
    RoleExample roleExample = new RoleExample();
    // 在Example對(duì)象中封裝查詢條件
    roleExample.createCriteria().andIdIn(roleIdList);
    // 執(zhí)行查詢
    return roleMapper.selectByExample(roleExample);
}

4.1.3 showRemoveConfirmModal()函數(shù)

// 打開刪除確認(rèn)模態(tài)框
function showRemoveConfirmModal() {
    // 1.將模態(tài)框顯示出來
    $("#confirmModal").modal("show");
    // 2.根據(jù)roleIdList獲取roleList
    var roleList = getRoleListByRoleIdArray(window.roleIdArray);
    // 3.清空#confirmModalTableBody
    $("#confirmModalTableBody").empty();
    // 4.填充#confirmModalTableBody
    for(var i = 0; i < roleList.length; i++) {
        // 5.獲取角色相關(guān)數(shù)據(jù)
        var role = roleList[i];
        var id = role.id;
        var name = role.name;
        var trHTML = "<tr><td>"+id+"</td><td>"+name+"</td></tr>";   
        // 6.執(zhí)行填充
        $("#confirmModalTableBody").append(trHTML);
    }   
}

4.2 給批量刪除按鈕綁定單擊響應(yīng)函數(shù)

4.2.1 標(biāo)記批量刪除按鈕

<button id="batchRemoveBtn" type="button" class="btn btn-danger"
        style="float: right; margin-left: 10px;">
    <i class=" glyphicon glyphicon-remove"></i> 批量刪除
</button>

4.2.2 檢查itemBox是否被選中

// 給批量刪除按鈕綁定單擊響應(yīng)函數(shù)
$("#batchRemoveBtn").click(function(){
    // 獲取被選中的itemBox數(shù)組長(zhǎng)度
    var length = $(".itemBox:checked").length;
    // 如果長(zhǎng)度為0,說明沒有選擇itemBox
    if(length == 0) {
        layer.msg("請(qǐng)至少選擇一條!");
        return ;
    }
    // 未完待續(xù)...
});

4.2.3 在彈出的模態(tài)框中顯示confirm信息

// 給批量刪除按鈕綁定單擊響應(yīng)函數(shù)
$("#batchRemoveBtn").click(function(){
    // 獲取被選中的itemBox數(shù)組長(zhǎng)度
    var length = $(".itemBox:checked").length;
    // 如果長(zhǎng)度為0,說明沒有選擇itemBox
    if(length == 0) {
        layer.msg("請(qǐng)至少選擇一條!");
        return ;
    }
    // 在全局作用域內(nèi)創(chuàng)建roleIdArray
    window.roleIdArray = new Array();
    // 遍歷$(".itemBox:checked")
    $(".itemBox:checked").each(function(){
        // 通過checkbox的roleid屬性獲取roleId值
        var roleId = $(this).attr("roleid");
        // 存入數(shù)組
        window.roleIdArray.push(roleId);
    });
    // 調(diào)用函數(shù)打開模態(tài)框
    showRemoveConfirmModal();
});

4.3 點(diǎn)擊模態(tài)框的OK按鈕執(zhí)行刪除

4.3.1 標(biāo)記OK按鈕

<button id="confirmModalBtn" type="button" class="btn btn-primary">OK</button>

4.3.2 綁定單擊響應(yīng)函數(shù)

// 給確認(rèn)模態(tài)框中的OK按鈕綁定單擊響應(yīng)函數(shù)
$("#confirmModalBtn").click(function(){
    var requestBody = JSON.stringify(window.roleIdArray);   
    $.ajax({
        "url":"role/batch/remove.json",
        "type":"post",
        "data":requestBody,
        "contentType":"application/json;charset=UTF-8",
        "dataType":"json",
        "success":function(response){
            var result = response.result;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");         
                // 如果刪除成功,則重新調(diào)用分頁(yè)方法
                showPage();
            }
            if(result == "FAILED") {
                layer.msg(response.message);
            }
            // 不管成功還是失敗,都需要關(guān)掉模態(tài)框
            $("#confirmModal").modal("hide");   
        },
        "error":function(response){
            layer.msg(response.message);
        }
    });
});

4.3.3 后端代碼

com.rgh.crowd.funding.handler.RoleHandler

@ResponseBody
@RequestMapping("/role/batch/remove")
public ResultEntity<String> batchRemove(@RequestBody List<Integer> roleIdList) {
    roleService.batchRemove(roleIdList);    
    return ResultEntity.successWithoutData();
}

com.rgh.crowd.funding.service.impl.RoleServiceImpl

@Override
public void batchRemove(List<Integer> roleIdList) {
    RoleExample roleExample = new RoleExample();
    roleExample.createCriteria().andIdIn(roleIdList);   
    roleMapper.deleteByExample(roleExample);
}

5 角色維護(hù)-單條刪除

// 針對(duì).removeBtn這樣動(dòng)態(tài)生成的元素對(duì)象使用on()函數(shù)方式綁定單擊響應(yīng)函數(shù)
// $("動(dòng)態(tài)元素所依附的靜態(tài)元素").on("事件類型","具體要綁定事件的動(dòng)態(tài)元素的選擇器", 事件響應(yīng)函數(shù));
$("#roleTableBody").on("click",".removeBtn", function(){
    // 獲取當(dāng)前記錄的roleId
    var roleId = $(this).attr("roleId");
    // 存入全局變量數(shù)組
    window.roleIdArray = new Array();
    window.roleIdArray.push(roleId);
    // 打開模態(tài)框(后續(xù)所有操作都和批量刪除一樣)
    showRemoveConfirmModal();
});

6 角色維護(hù)-新增

6.1 大體步驟

  • 給“新增”按鈕綁定單擊響應(yīng)函數(shù)
  • 打開模態(tài)框
  • 給“保存”按鈕綁定單擊響應(yīng)函數(shù)
    • 收集文本框內(nèi)容
    • 發(fā)送請(qǐng)求
  • 請(qǐng)求處理完成關(guān)閉模態(tài)框、重新分頁(yè)、清理表單

6.2 給“新增”按鈕綁定單擊響應(yīng)函數(shù)

6.2.1 標(biāo)記“新增”按鈕

<button id="addBtn" type="button" class="btn btn-primary"
        style="float: right;" >
    <i class="glyphicon glyphicon-plus"></i> 新增
</button>

6.2.2 綁定單擊響應(yīng)函數(shù)

$("#addBtn").click(function(){
    alert("aaa...");
});

6.3 打開模態(tài)框

6.3.1 準(zhǔn)備模態(tài)框

先準(zhǔn)備模態(tài)框的HTML代碼

<div id="addModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <form role="form">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal"
                            aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h4 class="modal-title">尚籌網(wǎng)系統(tǒng)彈窗</h4>
                </div>
                <div class="modal-body">
                    <input type="text" id="roleNameInput" class="form-control" placeholder="請(qǐng)輸入角色名稱" />
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i> 保存</button>
                    <button type="reset" class="btn btn-primary"><i class="glyphicon glyphicon-refresh"></i> 重置</button>
                </div>
            </form>
        </div>
    </div>
</div>

創(chuàng)建/atcrowdfunding-admin-1-webui/src/main/webapp/WEB-INF/include-modal-role-add.jsp文件

將include-modal-role-add.jsp包含到role-page.jsp

<%@ include file="/WEB-INF/include-modal-role-add.jsp" %>

6.3.2 打開模態(tài)框

$("#addBtn").click(function(){
    $("#addModal").modal("show");
});

6.4 給“保存”按鈕綁定單擊響應(yīng)函數(shù)

6.4.1 標(biāo)記“保存”按鈕

<button id="addModalBtn" type="button" class="btn btn-success">
    <i class="glyphicon glyphicon-plus"></i>保存
</button>

6.4.2 綁定單擊響應(yīng)函數(shù)

$("#addModalBtn").click(function(){
    // 1.收集文本框內(nèi)容
    var roleName = $.trim($("#roleNameInput").val());
    if(roleName == null || roleName == "") {
        layer.msg("請(qǐng)輸入有效角色名稱!");
        return ;
    }
    // 2.發(fā)送請(qǐng)求
    $.ajax({
        "url":"role/save/role.json",
        "type":"post",
        "data":{
            "roleName":roleName
        },
        "dataType":"json",
        "success":function(response){
            var result = response.result;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");
                // 3.操作成功重新分頁(yè)
                // 前往最后一頁(yè)
                window.pageNum = 999999;
                showPage();
            }
            if(result == "FAILED") {
                layer.msg(response.message);
            }
            // 4.不管成功還是失敗,關(guān)閉模態(tài)框
            $("#addModal").modal("hide");
            // 5.清理本次在文本框填寫的數(shù)據(jù)
            $("#roleNameInput").val("");
        },
        "error":function(response){
            layer.msg(response.message);
        }
    });
});

6.5 后端代碼

com.rgh.crowd.funding.handler.RoleHandler

@ResponseBody
@RequestMapping("/role/save/role")
public ResultEntity<String> saveRole(@RequestParam("roleName") String roleName) {   
    roleService.saveRole(roleName);
    return ResultEntity.successWithoutData();
}

com.rgh.crowd.funding.service.impl.RoleServiceImpl

@Override
public void saveRole(String roleName) {
    roleMapper.insert(new Role(null, roleName));
}

7 角色維護(hù)-更新

7.1 大體步驟

  • 給“鉛筆”按鈕綁定單擊響應(yīng)函數(shù)

    因?yàn)椤般U筆”按鈕是動(dòng)態(tài)生成的,所以需要使用on()方式

  • 打開模態(tài)框

    • 準(zhǔn)備模態(tài)框
    • 把roleId保存到全局變量
    • 獲取到當(dāng)前“鉛筆”按鈕所在行的roleName
    • 使用roleName回顯模態(tài)框中的表單
  • 給“更新”按鈕綁定單擊響應(yīng)函數(shù)

    • 收集文本框內(nèi)容
    • 發(fā)送請(qǐng)求
    • 請(qǐng)求處理完成關(guān)閉模態(tài)框、重新分頁(yè)

7.2 給“鉛筆”按鈕綁定單擊響應(yīng)函數(shù)

7.2.1 標(biāo)記“鉛筆”按鈕

找到/atcrowdfunding-admin-1-webui/src/main/webapp/script/my-role.js文件

function generateTableBody(pageInfo) {
    ……
    for(var i = 0; i < list.length; i++) {
        ……
        var pencilBtn = "<button roleId='"+role.id+"' type='button' class='btn btn-primary btn-xs editBtn'><i class=' glyphicon glyphicon-pencil'></i></button>";       
        ……
    }
}

7.2.2 準(zhǔn)備模態(tài)框

<div id="editModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <form role="form">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal"
                            aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h4 class="modal-title">尚籌網(wǎng)系統(tǒng)彈窗</h4>
                </div>
                <div class="modal-body">
                    <input type="text" id="roleNameInputEdit" class="form-control"
                           placeholder="請(qǐng)輸入角色名稱" />
                </div>
                <div class="modal-footer">
                    <button id="editModalBtn" type="button" class="btn btn-warning">
                        <i class="glyphicon glyphicon-edit"></i> 更新
                    </button>
                    <button type="reset" class="btn btn-primary">
                        <i class="glyphicon glyphicon-refresh"></i> 重置
                    </button>               </div>
            </form>
        </div>
    </div>
</div>
<%@ include file="/WEB-INF/include-modal-role-edit.jsp" %>

7.2.3 綁定單擊響應(yīng)函數(shù)

$("#roleTableBody").on("click",".editBtn",function(){
    // 1.獲取當(dāng)前按鈕的roleId
    window.roleId = $(this).attr("roleId");
    // 2.獲取當(dāng)前按鈕所在行的roleName
    var roleName = $(this).parents("tr").children("td:eq(2)").text();
    // 3.修改模態(tài)框中文本框的value值,目的是在顯示roleName
    $("#roleNameInputEdit").val(roleName);
    // 4.打開模態(tài)框
    $("#editModal").modal("show");
});

7.3 給“更新”按鈕綁定單擊響應(yīng)函數(shù)

7.3.1 前端代碼

$("#editModalBtn").click(function(){
    // 1.獲取文本框值
    var roleName = $.trim($("#roleNameInputEdit").val());
    if(roleName == null || roleName == "") {
        layer.msg("請(qǐng)輸入有效角色名稱!");
        return ;
    }
    // 2.發(fā)送請(qǐng)求
    $.ajax({
        "url":"role/update/role.json",
        "type":"post",
        "data":{
            "id":window.roleId,
            "name":roleName
        },
        "dataType":"json",
        "success":function(response){
            var result = response.result;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");
                // 3.操作成功重新分頁(yè)
                showPage();
            }
            if(result == "FAILED") {
                layer.msg(response.message);
            }
            // 4.不管成功還是失敗,關(guān)閉模態(tài)框
            $("#editModal").modal("hide");
        }
    });
});

7.3.2 后端代碼

@ResponseBody
@RequestMapping("/role/update/role")
public ResultEntity<String> updateRole(Role role) {
    roleService.updateRole(role);   
    return ResultEntity.successWithoutData();
}
@Override
public void updateRole(Role role) {
    roleMapper.updateByPrimaryKey(role);
}

8 @RestController

相當(dāng)于@Controller注解+@ResponseBody注解,類使用了@RestController之后相當(dāng)于在每一個(gè)方法上都加了@ResponseBody注解。

9 異常映射兼容異步請(qǐng)求

9.1 問題表現(xiàn)

Ajax請(qǐng)求在服務(wù)器端處理過程中拋出異常,經(jīng)過異常處理器:

com.rgh.crowd.funding.exception.CrowFundingExceptionResolever

@ControllerAdvice
public class CrowdFundingExceptionResolever {
    @ExceptionHandler(value=Exception.class)
    public ModelAndView catchException(Exception exception) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", exception);
        mav.setViewName("system-error");    
        return mav;
    }
}

目前這個(gè)異常處理機(jī)制,只能返回頁(yè)面,而不能針對(duì)Ajax請(qǐng)求返回JSON格式的響應(yīng)數(shù)據(jù)。所以Ajax請(qǐng)求處理過程中,如果拋出異常,返回異常信息頁(yè)面,Ajax程序無法正常解析,導(dǎo)致頁(yè)面不能正常顯示和工作,也不能給出友好的錯(cuò)誤提示。

9.2 問題解決思路

9.3 異步請(qǐng)求特點(diǎn)

9.4 分辨異步請(qǐng)求的工具方法

在atcrowdfunding-admin-3-common工程加入servlet-api依賴

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <scope>provided</scope>
</dependency>

com.rgh.crowd.funding.util.CrowdFundingUtils

/**
 * 用于判斷一個(gè)請(qǐng)求是否是異步請(qǐng)求
 * @param request
 * @return
 */
public static boolean checkAsyncRequest(HttpServletRequest request) {
    // 1.獲取相應(yīng)請(qǐng)求消息頭
    String accept = request.getHeader("Accept");
    String xRequested = request.getHeader("X-Requested-With");
    // 2.判斷請(qǐng)求消息頭數(shù)據(jù)中是否包含目標(biāo)特征
    if(
        (stringEffective(accept) && accept.contains("application/json")) 
        || 
        (stringEffective(xRequested) && xRequested.contains("XMLHttpRequest")) ) {
        return true;
    }   
    return false;
}

9.5 升級(jí)后的異常處理器

@ControllerAdvice
public class CrowdFundingExceptionResolever {
    @ExceptionHandler(value=Exception.class)
    public ModelAndView catchException(
            Exception exception, 
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        // 1.對(duì)當(dāng)前請(qǐng)求進(jìn)行檢查
        boolean checkAsyncRequestResult = CrowdFundingUtils.checkAsyncRequest(request);
        // 2.如果是異步請(qǐng)求
        if(checkAsyncRequestResult) {
            // 3.創(chuàng)建ResultEntity對(duì)象
            ResultEntity<String> resultEntity = ResultEntity.failed(ResultEntity.NO_DATA, exception.getMessage());
            // 4.將resultEntity轉(zhuǎn)換為JSON格式
            Gson gson = new Gson();
            String json = gson.toJson(resultEntity);
            // 5.將json作為響應(yīng)數(shù)據(jù)返回給瀏覽器
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(json);   
            return null;
        }
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", exception);
        mav.setViewName("system-error");    
        return mav;
    }
}

※需要Gson支持

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>

9.6 改進(jìn)提示消息

  • 所在工程:atcrowdfunding-admin-3-common
  • 全類名:com.rgh.crowd.funding.util.CrowdFundingConstant
public static final Map<String, String> EXCEPTION_MESSAGE_MAP = new HashMap<>();
static {
    EXCEPTION_MESSAGE_MAP.put("java.lang.ArithmeticException", "系統(tǒng)在進(jìn)行數(shù)學(xué)運(yùn)算時(shí)發(fā)生錯(cuò)誤");
    EXCEPTION_MESSAGE_MAP.put("java.lang.RuntimeException", "系統(tǒng)在運(yùn)行時(shí)發(fā)生錯(cuò)誤");
    EXCEPTION_MESSAGE_MAP.put("com.rgh.crowd.funding.exception.LoginException", "登錄過程中運(yùn)行錯(cuò)誤");
}
  • 所在工程:atcrowdfunding-admin-2-component
  • 全類名:com.rgh.crowd.funding.exeption.CrowdFundingExceptionResolever
@ControllerAdvice
public class CrowdFundingExceptionResolever {
    @ExceptionHandler(value=Exception.class)
    public ModelAndView catchException(
        Exception exception, 
        HttpServletRequest request,
        HttpServletResponse response) throws IOException {
        // 1.對(duì)當(dāng)前請(qǐng)求進(jìn)行檢查
        boolean checkAsyncRequestResult = CrowdFundingUtils.checkAsyncRequest(request);
        // 2.如果是異步請(qǐng)求
        if(checkAsyncRequestResult) {
            // 根據(jù)異常類型在常量中的映射,使用比較友好的文字顯示錯(cuò)誤提示消息
            String exceptionClassName = exception.getClass().getName();
            String message = CrowdFundingConstant.EXCEPTION_MESSAGE_MAP.get(exceptionClassName);
            if(message == null) {
                message = "系統(tǒng)未知錯(cuò)誤";
            }
            // 3.創(chuàng)建ResultEntity對(duì)象
            ResultEntity<String> resultEntity = ResultEntity.failed(ResultEntity.NO_DATA, message);
            // 4.將resultEntity轉(zhuǎn)換為JSON格式
            Gson gson = new Gson();
            String json = gson.toJson(resultEntity);
            // 5.將json作為響應(yīng)數(shù)據(jù)返回給瀏覽器
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(json);   
            return null;
        }
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", exception);
        mav.setViewName("system-error");    
        return mav;
    }
}

10 登錄攔截器兼容異步請(qǐng)求

問題的產(chǎn)生和解決的思路都和異常映射部分一致

com.rgh.crowd.funding.interceptor.LoginInterceptor

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    throws Exception {
    // 通過request對(duì)象獲取HttpSession對(duì)象
    HttpSession session = request.getSession(); 
    // 從Session域嘗試獲取已登錄用戶對(duì)象
    Admin admin = (Admin) session.getAttribute(CrowdFundingConstant.ATTR_NAME_LOGIN_ADMIN); 
    // 如果沒有獲取到Admin對(duì)象
    if(admin == null) {     
        // 進(jìn)一步判斷當(dāng)前請(qǐng)求是否是異步請(qǐng)求
        boolean checkAsyncRequestResult = CrowdFundingUtils.checkAsyncRequest(request);
        if(checkAsyncRequestResult) {           
            // 為異步請(qǐng)求的響應(yīng)創(chuàng)建ResultEntity對(duì)象
            ResultEntity<String> resultEntity = ResultEntity.failed(ResultEntity.NO_DATA, CrowdFundingConstant.MESSAGE_ACCESS_DENIED);          
            // 創(chuàng)建Gson對(duì)象
            Gson gson = new Gson();         
            // 將ResultEntity對(duì)象轉(zhuǎn)換為JSON字符串
            String json = gson.toJson(resultEntity);            
            // 設(shè)置響應(yīng)的內(nèi)容類型
            response.setContentType("application/json;charset=UTF-8");
            // 將JSON字符串作為響應(yīng)數(shù)據(jù)返回
            response.getWriter().write(json);
            // 表示不能放行,后續(xù)操作不執(zhí)行
            return false;   
        }
        // 將提示消息存入request域
        request.setAttribute(CrowdFundingConstant.ATTR_NAME_MESSAGE, CrowdFundingConstant.MESSAGE_ACCESS_DENIED);
        // 轉(zhuǎn)發(fā)到登錄頁(yè)面
        request.getRequestDispatcher("/WEB-INF/admin-login.jsp").forward(request, response);    
        return false;
    }   
    // 如果admin對(duì)象有效,則放行繼續(xù)執(zhí)行后續(xù)操作
    return true;
}

11 分頁(yè)的showPage()函數(shù)修正

// 給服務(wù)器發(fā)送請(qǐng)求獲取分頁(yè)數(shù)據(jù)(pageInfo),并在頁(yè)面上顯示分頁(yè)效果(主體、頁(yè)碼導(dǎo)航條)
function showPage() {   
    // 給服務(wù)器發(fā)送請(qǐng)求獲取分頁(yè)數(shù)據(jù):PageInfo
    var pageInfo = getPageInfo();
    console.log(pageInfo);  
    if(pageInfo == null) {
        // 如果沒有獲取到pageInfo數(shù)據(jù),則停止后續(xù)操作
        return ;
    }   
    // 在頁(yè)面上的表格中tbody標(biāo)簽內(nèi)顯示分頁(yè)的主體數(shù)據(jù)
    generateTableBody(pageInfo);    
    // 在頁(yè)面上的表格中tfoot標(biāo)簽內(nèi)顯示分頁(yè)的頁(yè)碼導(dǎo)航條
    initPagination(pageInfo);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容