国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

這篇具有很好參考價(jià)值的文章主要介紹了【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1,統(tǒng)一異常處理

1. 問題描述

在講解這一部分知識(shí)點(diǎn)之前,我們先來演示個(gè)效果,修改BookController類的getById方法

@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
    //手動(dòng)添加一個(gè)錯(cuò)誤信息
    if(id==1){
        int i = 1/0;
    }
    Book book = bookService.getById(id);
    Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
    String msg = book != null ? "" : "數(shù)據(jù)查詢失敗,請(qǐng)重試!";
    return new Result(code,book,msg);
}

重新啟動(dòng)運(yùn)行項(xiàng)目,使用PostMan發(fā)送請(qǐng)求,當(dāng)傳入的id為1,則會(huì)出現(xiàn)如下效果:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

前端接收到這個(gè)信息后和之前我們約定的格式不一致,這個(gè)問題該如何解決?

在解決問題之前,我們先來看下異常的種類及出現(xiàn)異常的原因:

  • 框架內(nèi)部拋出的異常:因使用不合規(guī)導(dǎo)致
  • 數(shù)據(jù)層拋出的異常:因外部服務(wù)器故障導(dǎo)致(例如:服務(wù)器訪問超時(shí))
  • 業(yè)務(wù)層拋出的異常:因業(yè)務(wù)邏輯書寫錯(cuò)誤導(dǎo)致(例如:遍歷業(yè)務(wù)書寫操作,導(dǎo)致索引異常等)
  • 表現(xiàn)層拋出的異常:因數(shù)據(jù)收集、校驗(yàn)等規(guī)則導(dǎo)致(例如:不匹配的數(shù)據(jù)類型間導(dǎo)致異常)
  • 工具類拋出的異常:因工具類書寫不嚴(yán)謹(jǐn)不夠健壯導(dǎo)致(例如:必要釋放的連接長(zhǎng)期未釋放等)

看完上面這些出現(xiàn)異常的位置,你會(huì)發(fā)現(xiàn),在我們開發(fā)的任何一個(gè)位置都有可能出現(xiàn)異常,而且這些異常是不能避免的。所以我們就得將異常進(jìn)行處理。

思考

  1. 各個(gè)層級(jí)均出現(xiàn)異常,異常處理代碼書寫在哪一層?

    所有的異常均拋出到表現(xiàn)層進(jìn)行處理

  2. 異常的種類很多,表現(xiàn)層如何將所有的異常都處理到呢?

    異常分類

  3. 表現(xiàn)層處理異常,每個(gè)方法中單獨(dú)書寫,代碼書寫量巨大且意義不強(qiáng),如何解決?

    AOP

對(duì)于上面這些問題及解決方案,SpringMVC已經(jīng)為我們提供了一套解決方案:

  • 異常處理器:

    • 集中的、統(tǒng)一的處理項(xiàng)目中出現(xiàn)的異常。

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

2. 異常處理器的使用

1. 環(huán)境準(zhǔn)備
  • 創(chuàng)建一個(gè)Web的Maven項(xiàng)目
  • pom.xml添加SSM整合所需jar包
  • 創(chuàng)建對(duì)應(yīng)的配置類
  • 編寫Controller、Service接口、Service實(shí)現(xiàn)類、Dao接口和模型類
  • resources下提供jdbc.properties配置文件

內(nèi)容參考前面的項(xiàng)目或者直接使用前面的項(xiàng)目進(jìn)行本節(jié)內(nèi)容的學(xué)習(xí)。

最終創(chuàng)建好的項(xiàng)目結(jié)構(gòu)如下:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

2. 使用步驟
步驟1:創(chuàng)建異常處理器類
//@RestControllerAdvice用于標(biāo)識(shí)當(dāng)前類為REST風(fēng)格對(duì)應(yīng)的異常處理器
@RestControllerAdvice
public class ProjectExceptionAdvice {
    //除了自定義的異常處理器,保留對(duì)Exception類型的異常處理,用于處理非預(yù)期的異常
    @ExceptionHandler(Exception.class)
    public void doException(Exception ex){
      	System.out.println("嘿嘿,異常你哪里跑!")
    }
}

確保SpringMvcConfig能夠掃描到異常處理器類

步驟2:讓程序拋出異常

修改BookController的getById方法,添加int i = 1/0.

@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
  	int i = 1/0;
    Book book = bookService.getById(id);
    Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
    String msg = book != null ? "" : "數(shù)據(jù)查詢失敗,請(qǐng)重試!";
    return new Result(code,book,msg);
}
步驟3:運(yùn)行程序,測(cè)試

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

說明異常已經(jīng)被攔截并執(zhí)行了doException方法。

異常處理器類返回結(jié)果給前端
//@RestControllerAdvice用于標(biāo)識(shí)當(dāng)前類為REST風(fēng)格對(duì)應(yīng)的異常處理器
@RestControllerAdvice
public class ProjectExceptionAdvice {
    //除了自定義的異常處理器,保留對(duì)Exception類型的異常處理,用于處理非預(yù)期的異常
    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
      	System.out.println("嘿嘿,異常你哪里跑!")
        return new Result(666,null,"嘿嘿,異常你哪里跑!");
    }
}

啟動(dòng)運(yùn)行程序,測(cè)試

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

至此,就算后臺(tái)執(zhí)行的過程中拋出異常,最終也能按照我們和前端約定好的格式返回給前端。

知識(shí)點(diǎn)1:@RestControllerAdvice
名稱 @RestControllerAdvice
類型 類注解
位置 Rest風(fēng)格開發(fā)的控制器增強(qiáng)類定義上方
作用 為Rest風(fēng)格開發(fā)的控制器類做增強(qiáng)

說明: 此注解自帶@ResponseBody注解與@Component注解,具備對(duì)應(yīng)的功能

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

知識(shí)點(diǎn)2:@ExceptionHandler
名稱 @ExceptionHandler
類型 方法注解
位置 專用于異常處理的控制器方法上方
作用 設(shè)置指定異常的處理方案,功能等同于控制器方法,
出現(xiàn)異常后終止原始控制器執(zhí)行,并轉(zhuǎn)入當(dāng)前方法執(zhí)行

說明 此類方法可以根據(jù)處理的異常不同,制作多個(gè)方法分別處理對(duì)應(yīng)的異常

3. 項(xiàng)目異常處理方案

1. 異常分類

異常處理器我們已經(jīng)能夠使用了,那么在咱們的項(xiàng)目中該如何來處理異常呢?

因?yàn)楫惓5姆N類有很多,如果每一個(gè)異常都對(duì)應(yīng)一個(gè)@ExceptionHandler,那得寫多少個(gè)方法來處理各自的異常,所以我們?cè)谔幚懋惓V?,需要?duì)異常進(jìn)行一個(gè)分類:

  • 業(yè)務(wù)異常(BusinessException)

    • 規(guī)范的用戶行為產(chǎn)生的異常

      • 用戶在頁(yè)面輸入內(nèi)容的時(shí)候未按照指定格式進(jìn)行數(shù)據(jù)填寫,如在年齡框輸入的是字符串

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

  • 不規(guī)范的用戶行為操作產(chǎn)生的異常

    • 如用戶故意傳遞錯(cuò)誤數(shù)據(jù)

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

  • 系統(tǒng)異常(SystemException)

    • 項(xiàng)目運(yùn)行過程中可預(yù)計(jì)但無(wú)法避免的異常
      • 比如數(shù)據(jù)庫(kù)或服務(wù)器宕機(jī)
  • 其他異常(Exception)

    • 編程人員未預(yù)期到的異常,如:用到的文件不存在

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

將異常分類以后,針對(duì)不同類型的異常,要提供具體的解決方案:

2. 異常解決方案
  • 業(yè)務(wù)異常(BusinessException)
    • 發(fā)送對(duì)應(yīng)消息傳遞給用戶,提醒規(guī)范操作
      • 大家常見的就是提示用戶名已存在或密碼格式不正確等
  • 系統(tǒng)異常(SystemException)
    • 發(fā)送固定消息傳遞給用戶,安撫用戶
      • 系統(tǒng)繁忙,請(qǐng)稍后再試
      • 系統(tǒng)正在維護(hù)升級(jí),請(qǐng)稍后再試
      • 系統(tǒng)出問題,請(qǐng)聯(lián)系系統(tǒng)管理員等
    • 發(fā)送特定消息給運(yùn)維人員,提醒維護(hù)
      • 可以發(fā)送短信、郵箱或者是公司內(nèi)部通信軟件
    • 記錄日志
      • 發(fā)消息和記錄日志對(duì)用戶來說是不可見的,屬于后臺(tái)程序
  • 其他異常(Exception)
    • 發(fā)送固定消息傳遞給用戶,安撫用戶
    • 發(fā)送特定消息給編程人員,提醒維護(hù)(納入預(yù)期范圍內(nèi))
      • 一般是程序沒有考慮全,比如未做非空校驗(yàn)等
    • 記錄日志
3. 異常解決方案的具體實(shí)現(xiàn)

思路:

1.先通過自定義異常,完成BusinessException和SystemException的定義

2.將其他異常包裝成自定義異常類型

3.在異常處理器類中對(duì)不同的異常進(jìn)行處理

步驟1:自定義異常類
//自定義異常處理器,用于封裝異常信息,對(duì)異常進(jìn)行分類
public class SystemException extends RuntimeException{
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}

//自定義異常處理器,用于封裝異常信息,對(duì)異常進(jìn)行分類
public class BusinessException extends RuntimeException{
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}


說明:

  • 讓自定義異常類繼承RuntimeException的好處是,后期在拋出這兩個(gè)異常的時(shí)候,就不用在try…catch…或throws了
  • 自定義異常類中添加code屬性的原因是為了更好的區(qū)分異常是來自哪個(gè)業(yè)務(wù)的
步驟2:將其他異常包成自定義異常

假如在BookServiceImpl的getById方法拋異常了,該如何來包裝呢?

public Book getById(Integer id) {
    //模擬業(yè)務(wù)異常,包裝成自定義異常
    if(id == 1){
        throw new BusinessException(Code.BUSINESS_ERR,"請(qǐng)不要使用你的技術(shù)挑戰(zhàn)我的耐性!");
    }
    //模擬系統(tǒng)異常,將可能出現(xiàn)的異常進(jìn)行包裝,轉(zhuǎn)換成自定義異常
    try{
        int i = 1/0;
    }catch (Exception e){
        throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服務(wù)器訪問超時(shí),請(qǐng)重試!",e);
    }
    return bookDao.getById(id);
}

具體的包裝方式有:

  • 方式一:try{}catch(){}在catch中重新throw我們自定義異常即可。
  • 方式二:直接throw自定義異常即可

上面為了使code看著更專業(yè)些,我們?cè)贑ode類中再新增需要的屬性

//狀態(tài)碼
public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;
    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;

    public static final Integer BUSINESS_ERR = 60002;
}

步驟3:處理器類中處理自定義異常
//@RestControllerAdvice用于標(biāo)識(shí)當(dāng)前類為REST風(fēng)格對(duì)應(yīng)的異常處理器
@RestControllerAdvice
public class ProjectExceptionAdvice {
    //@ExceptionHandler用于設(shè)置當(dāng)前處理器類對(duì)應(yīng)的異常類型
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex){
        //記錄日志
        //發(fā)送消息給運(yùn)維
        //發(fā)送郵件給開發(fā)人員,ex對(duì)象發(fā)送給開發(fā)人員
        return new Result(ex.getCode(),null,ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex){
        return new Result(ex.getCode(),null,ex.getMessage());
    }

    //除了自定義的異常處理器,保留對(duì)Exception類型的異常處理,用于處理非預(yù)期的異常
    @ExceptionHandler(Exception.class)
    public Result doOtherException(Exception ex){
        //記錄日志
        //發(fā)送消息給運(yùn)維
        //發(fā)送郵件給開發(fā)人員,ex對(duì)象發(fā)送給開發(fā)人員
        return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系統(tǒng)繁忙,請(qǐng)稍后再試!");
    }
}
步驟4:運(yùn)行程序

根據(jù)ID查詢,

如果傳入的參數(shù)為1,會(huì)報(bào)BusinessException

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

如果傳入的是其他參數(shù),會(huì)報(bào)SystemException

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

對(duì)于異常我們就已經(jīng)處理完成了,不管后臺(tái)哪一層拋出異常,都會(huì)以我們與前端約定好的方式進(jìn)行返回,前端只需要把信息獲取到,根據(jù)返回的正確與否來展示不同的內(nèi)容即可。

小結(jié)

以后項(xiàng)目中的異常處理方式為:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

2,前后臺(tái)協(xié)議聯(lián)調(diào)

1. 環(huán)境準(zhǔn)備

  • 創(chuàng)建一個(gè)Web的Maven項(xiàng)目
  • pom.xml添加SSM整合所需jar包
  • 創(chuàng)建對(duì)應(yīng)的配置類
  • 編寫Controller、Service接口、Service實(shí)現(xiàn)類、Dao接口和模型類
  • resources下提供jdbc.properties配置文件

內(nèi)容參考前面的項(xiàng)目或者直接使用前面的項(xiàng)目進(jìn)行本節(jié)內(nèi)容的學(xué)習(xí)。

最終創(chuàng)建好的項(xiàng)目結(jié)構(gòu)如下:
【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

  1. 資料\SSM功能頁(yè)面下面的靜態(tài)資源拷貝到webapp下。

鏈接:https://pan.baidu.com/s/1Nu1jT–H00csTU48c7TyVg?pwd=0kfh
提取碼:0kfh

  1. 因?yàn)樘砑恿遂o態(tài)資源,SpringMVC會(huì)攔截,所有需要在SpringConfig的配置類中將靜態(tài)資源進(jìn)行放行。
  • 新建SpringMvcSupport

    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport {
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
            registry.addResourceHandler("/css/**").addResourceLocations("/css/");
            registry.addResourceHandler("/js/**").addResourceLocations("/js/");
            registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
        }
    }
    
  • 在SpringMvcConfig中掃描SpringMvcSupport

    @Configuration
    @ComponentScan({"com.itheima.controller","com.itheima.config"})
    @EnableWebMvc
    public class SpringMvcConfig {
    }
    

接下來我們就需要將所有的列表查詢、新增、修改、刪除等功能一個(gè)個(gè)來實(shí)現(xiàn)下。

2. 列表功能

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

需求:頁(yè)面加載完后發(fā)送異步請(qǐng)求到后臺(tái)獲取列表數(shù)據(jù)進(jìn)行展示。

1.找到頁(yè)面的鉤子函數(shù),created()

2.created()方法中調(diào)用了this.getAll()方法

3.在getAll()方法中使用axios發(fā)送異步請(qǐng)求從后臺(tái)獲取數(shù)據(jù)

4.訪問的路徑為http://localhost/books

5.返回?cái)?shù)據(jù)

返回?cái)?shù)據(jù)res.data的內(nèi)容如下:

{
    "data": [
        {
            "id": 1,
            "type": "計(jì)算機(jī)理論",
            "name": "Spring實(shí)戰(zhàn) 第五版",
            "description": "Spring入門經(jīng)典教程,深入理解Spring原理技術(shù)內(nèi)幕"
        },
        {
            "id": 2,
            "type": "計(jì)算機(jī)理論",
            "name": "Spring 5核心原理與30個(gè)類手寫實(shí)踐",
            "description": "十年沉淀之作,手寫Spring精華思想"
        },...
    ],
    "code": 20041,
    "msg": ""
}

發(fā)送方式:

getAll() {
    //發(fā)送ajax請(qǐng)求
    axios.get("/books").then((res)=>{
        this.dataList = res.data.data;
    });
}

3. 添加功能

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

需求:完成圖片的新增功能模塊

1.找到頁(yè)面上的新建按鈕,按鈕上綁定了@click="handleCreate()"方法

2.在method中找到handleCreate方法,方法中打開新增面板

3.新增面板中找到確定按鈕,按鈕上綁定了@click="handleAdd()"方法

4.在method中找到handleAdd方法

5.在方法中發(fā)送請(qǐng)求和數(shù)據(jù),響應(yīng)成功后將新增面板關(guān)閉并重新查詢數(shù)據(jù)

handleCreate打開新增面板

handleCreate() {
    this.dialogFormVisible = true;
},

handleAdd方法發(fā)送異步請(qǐng)求并攜帶數(shù)據(jù)

handleAdd () {
    //發(fā)送ajax請(qǐng)求
    //this.formData是表單中的數(shù)據(jù),最后是一個(gè)json數(shù)據(jù)
    axios.post("/books",this.formData).then((res)=>{
        this.dialogFormVisible = false;
        this.getAll();
    });
}

4. 添加功能狀態(tài)處理

基礎(chǔ)的新增功能已經(jīng)完成,但是還有一些問題需要解決下:

需求:新增成功是關(guān)閉面板,重新查詢數(shù)據(jù),那么新增失敗以后該如何處理?

1.在handlerAdd方法中根據(jù)后臺(tái)返回的數(shù)據(jù)來進(jìn)行不同的處理

2.如果后臺(tái)返回的是成功,則提示成功信息,并關(guān)閉面板

3.如果后臺(tái)返回的是失敗,則提示錯(cuò)誤信息

(1)修改前端頁(yè)面

handleAdd () {
    //發(fā)送ajax請(qǐng)求
    axios.post("/books",this.formData).then((res)=>{
        //如果操作成功,關(guān)閉彈層,顯示數(shù)據(jù)
        if(res.data.code == 20011){
            this.dialogFormVisible = false;
            this.$message.success("添加成功");
        }else if(res.data.code == 20010){
            this.$message.error("添加失敗");
        }else{
            this.$message.error(res.data.msg);
        }
    }).finally(()=>{
        this.getAll();
    });
}

(2)后臺(tái)返回操作結(jié)果,將Dao層的增刪改方法返回值從void改成int

public interface BookDao {

//    @Insert("insert into tbl_book values(null,#{type},#{name},#{description})")
    @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})")
    public int save(Book book);

    @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
    public int update(Book book);

    @Delete("delete from tbl_book where id = #{id}")
    public int delete(Integer id);

    @Select("select * from tbl_book where id = #{id}")
    public Book getById(Integer id);

    @Select("select * from tbl_book")
    public List<Book> getAll();
}

(3)在BookServiceImpl中,增刪改方法根據(jù)DAO的返回值來決定返回true/false

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;

    public boolean save(Book book) {
        return bookDao.save(book) > 0;
    }

    public boolean update(Book book) {
        return bookDao.update(book) > 0;
    }

    public boolean delete(Integer id) {
        return bookDao.delete(id) > 0;
    }

    public Book getById(Integer id) {
        if(id == 1){
            throw new BusinessException(Code.BUSINESS_ERR,"請(qǐng)不要使用你的技術(shù)挑戰(zhàn)我的耐性!");
        }
//        //將可能出現(xiàn)的異常進(jìn)行包裝,轉(zhuǎn)換成自定義異常
//        try{
//            int i = 1/0;
//        }catch (Exception e){
//            throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服務(wù)器訪問超時(shí),請(qǐng)重試!",e);
//        }
        return bookDao.getById(id);
    }

    public List<Book> getAll() {
        return bookDao.getAll();
    }
}

(4)測(cè)試錯(cuò)誤情況,將圖書類別長(zhǎng)度設(shè)置超出范圍即可

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

處理完新增后,會(huì)發(fā)現(xiàn)新增還存在一個(gè)問題,

新增成功后,再次點(diǎn)擊新增按鈕會(huì)發(fā)現(xiàn)之前的數(shù)據(jù)還存在,這個(gè)時(shí)候就需要在新增的時(shí)候?qū)⒈韱蝺?nèi)容清空。

resetForm(){
	this.formData = {};
}
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
}

5. 修改功能

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

需求:完成圖書信息的修改功能

1.找到頁(yè)面中的編輯按鈕,該按鈕綁定了@click="handleUpdate(scope.row)"

2.在method的handleUpdate方法中發(fā)送異步請(qǐng)求根據(jù)ID查詢圖書信息

3.根據(jù)后臺(tái)返回的結(jié)果,判斷是否查詢成功

? 如果查詢成功打開修改面板回顯數(shù)據(jù),如果失敗提示錯(cuò)誤信息

4.修改完成后找到修改面板的確定按鈕,該按鈕綁定了@click="handleEdit()"

5.在method的handleEdit方法中發(fā)送異步請(qǐng)求提交修改數(shù)據(jù)

6.根據(jù)后臺(tái)返回的結(jié)果,判斷是否修改成功

? 如果成功提示錯(cuò)誤信息,關(guān)閉修改面板,重新查詢數(shù)據(jù),如果失敗提示錯(cuò)誤信息

scope.row代表的是當(dāng)前行的行數(shù)據(jù),也就是說,scope.row就是選中行對(duì)應(yīng)的json數(shù)據(jù),如下:

{
    "id": 1,
    "type": "計(jì)算機(jī)理論",
    "name": "Spring實(shí)戰(zhàn) 第五版",
    "description": "Spring入門經(jīng)典教程,深入理解Spring原理技術(shù)內(nèi)幕"
}

修改handleUpdate方法

//彈出編輯窗口
handleUpdate(row) {
    // console.log(row);   //row.id 查詢條件
    //查詢數(shù)據(jù),根據(jù)id查詢
    axios.get("/books/"+row.id).then((res)=>{
        if(res.data.code == 20041){
            //展示彈層,加載數(shù)據(jù)
            this.formData = res.data.data;
            this.dialogFormVisible4Edit = true;
        }else{
            this.$message.error(res.data.msg);
        }
    });
}

修改handleEdit方法

handleEdit() {
    //發(fā)送ajax請(qǐng)求
    axios.put("/books",this.formData).then((res)=>{
        //如果操作成功,關(guān)閉彈層,顯示數(shù)據(jù)
        if(res.data.code == 20031){
            this.dialogFormVisible4Edit = false;
            this.$message.success("修改成功");
        }else if(res.data.code == 20030){
            this.$message.error("修改失敗");
        }else{
            this.$message.error(res.data.msg);
        }
    }).finally(()=>{
        this.getAll();
    });
}

至此修改功能就已經(jīng)完成。

6 刪除功能

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

需求:完成頁(yè)面的刪除功能。

1.找到頁(yè)面的刪除按鈕,按鈕上綁定了@click="handleDelete(scope.row)"

2.method的handleDelete方法彈出提示框

3.用戶點(diǎn)擊取消,提示操作已經(jīng)被取消。

4.用戶點(diǎn)擊確定,發(fā)送異步請(qǐng)求并攜帶需要?jiǎng)h除數(shù)據(jù)的主鍵ID

5.根據(jù)后臺(tái)返回結(jié)果做不同的操作

? 如果返回成功,提示成功信息,并重新查詢數(shù)據(jù)

? 如果返回失敗,提示錯(cuò)誤信息,并重新查詢數(shù)據(jù)

修改handleDelete方法

handleDelete(row) {
    //1.彈出提示框
    this.$confirm("此操作永久刪除當(dāng)前數(shù)據(jù),是否繼續(xù)?","提示",{
        type:'info'
    }).then(()=>{
        //2.做刪除業(yè)務(wù)
        axios.delete("/books/"+row.id).then((res)=>{
            if(res.data.code == 20021){
                this.$message.success("刪除成功");
            }else{
                this.$message.error("刪除失敗");
            }
        }).finally(()=>{
            this.getAll();
        });
    }).catch(()=>{
        //3.取消刪除
        this.$message.info("取消刪除操作");
    });
}

接下來,下面是一個(gè)完整頁(yè)面

<!DOCTYPE html>

<html>

    <head>

        <!-- 頁(yè)面meta -->

        <meta charset="utf-8">

        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <title>SpringMVC案例</title>

        <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">

        <!-- 引入樣式 -->

        <link rel="stylesheet" href="../plugins/elementui/index.css">

        <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">

        <link rel="stylesheet" href="../css/style.css">

    </head>

    <body class="hold-transition">

        <div id="app">

            <div class="content-header">

                <h1>圖書管理</h1>

            </div>

            <div class="app-container">

                <div class="box">

                    <div class="filter-container">

                        <el-input placeholder="圖書名稱" v-model="pagination.queryString" style="width: 200px;" class="filter-item"></el-input>

                        <el-button @click="getAll()" class="dalfBut">查詢</el-button>

                        <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>

                    </div>

                    <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>

                        <el-table-column type="index" align="center" label="序號(hào)"></el-table-column>

                        <el-table-column prop="type" label="圖書類別" align="center"></el-table-column>

                        <el-table-column prop="name" label="圖書名稱" align="center"></el-table-column>

                        <el-table-column prop="description" label="描述" align="center"></el-table-column>

                        <el-table-column label="操作" align="center">

                            <template slot-scope="scope">

                                <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">編輯</el-button>

                                <el-button type="danger" size="mini" @click="handleDelete(scope.row)">刪除</el-button>

                            </template>

                        </el-table-column>

                    </el-table>

                    <!-- 新增標(biāo)簽彈層 -->

                    <div class="add-form">

                        <el-dialog title="新增圖書" :visible.sync="dialogFormVisible">

                            <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px">

                                <el-row>

                                    <el-col :span="12">

                                        <el-form-item label="圖書類別" prop="type">

                                            <el-input v-model="formData.type"/>

                                        </el-form-item>

                                    </el-col>

                                    <el-col :span="12">

                                        <el-form-item label="圖書名稱" prop="name">

                                            <el-input v-model="formData.name"/>

                                        </el-form-item>

                                    </el-col>

                                </el-row>


                                <el-row>

                                    <el-col :span="24">

                                        <el-form-item label="描述">

                                            <el-input v-model="formData.description" type="textarea"></el-input>

                                        </el-form-item>

                                    </el-col>

                                </el-row>

                            </el-form>

                            <div slot="footer" class="dialog-footer">

                                <el-button @click="dialogFormVisible = false">取消</el-button>

                                <el-button type="primary" @click="handleAdd()">確定</el-button>

                            </div>

                        </el-dialog>

                    </div>

                    <!-- 編輯標(biāo)簽彈層 -->

                    <div class="add-form">

                        <el-dialog title="編輯檢查項(xiàng)" :visible.sync="dialogFormVisible4Edit">

                            <el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right" label-width="100px">

                                <el-row>

                                    <el-col :span="12">

                                        <el-form-item label="圖書類別" prop="type">

                                            <el-input v-model="formData.type"/>

                                        </el-form-item>

                                    </el-col>

                                    <el-col :span="12">

                                        <el-form-item label="圖書名稱" prop="name">

                                            <el-input v-model="formData.name"/>

                                        </el-form-item>

                                    </el-col>

                                </el-row>

                                <el-row>

                                    <el-col :span="24">

                                        <el-form-item label="描述">

                                            <el-input v-model="formData.description" type="textarea"></el-input>

                                        </el-form-item>

                                    </el-col>

                                </el-row>

                            </el-form>

                            <div slot="footer" class="dialog-footer">

                                <el-button @click="dialogFormVisible4Edit = false">取消</el-button>

                                <el-button type="primary" @click="handleEdit()">確定</el-button>

                            </div>

                        </el-dialog>

                    </div>

                </div>

            </div>

        </div>

    </body>

    <!-- 引入組件庫(kù) -->

    <script src="../js/vue.js"></script>

    <script src="../plugins/elementui/index.js"></script>

    <script type="text/javascript" src="../js/jquery.min.js"></script>

    <script src="../js/axios-0.18.0.js"></script>

    <script>
        var vue = new Vue({

            el: '#app',
            data:{
                pagination: {},
				dataList: [],//當(dāng)前頁(yè)要展示的列表數(shù)據(jù)
                formData: {},//表單數(shù)據(jù)
                dialogFormVisible: false,//控制表單是否可見
                dialogFormVisible4Edit:false,//編輯表單是否可見
                rules: {//校驗(yàn)規(guī)則
                    type: [{ required: true, message: '圖書類別為必填項(xiàng)', trigger: 'blur' }],
                    name: [{ required: true, message: '圖書名稱為必填項(xiàng)', trigger: 'blur' }]
                }
            },

            //鉤子函數(shù),VUE對(duì)象初始化完成后自動(dòng)執(zhí)行
            created() {
                this.getAll();
            },

            methods: {
                //列表
                getAll() {
                    //發(fā)送ajax請(qǐng)求
                    axios.get("/books").then((res)=>{
                        this.dataList = res.data.data;
                    });
                },

                //彈出添加窗口
                handleCreate() {
                    this.dialogFormVisible = true;
                    this.resetForm();
                },

                //重置表單
                resetForm() {
                    this.formData = {};
                },

                //添加
                handleAdd () {
                    //發(fā)送ajax請(qǐng)求
                    axios.post("/books",this.formData).then((res)=>{
                        console.log(res.data);
                        //如果操作成功,關(guān)閉彈層,顯示數(shù)據(jù)
                        if(res.data.code == 20011){
                            this.dialogFormVisible = false;
                            this.$message.success("添加成功");
                        }else if(res.data.code == 20010){
                            this.$message.error("添加失敗");
                        }else{
                            this.$message.error(res.data.msg);
                        }
                    }).finally(()=>{
                        this.getAll();
                    });
                },

                //彈出編輯窗口
                handleUpdate(row) {
                    // console.log(row);   //row.id 查詢條件
                    //查詢數(shù)據(jù),根據(jù)id查詢
                    axios.get("/books/"+row.id).then((res)=>{
                        // console.log(res.data.data);
                        if(res.data.code == 20041){
                            //展示彈層,加載數(shù)據(jù)
                            this.formData = res.data.data;
                            this.dialogFormVisible4Edit = true;
                        }else{
                            this.$message.error(res.data.msg);
                        }
                    });
                },

                //編輯
                handleEdit() {
                    //發(fā)送ajax請(qǐng)求
                    axios.put("/books",this.formData).then((res)=>{
                        //如果操作成功,關(guān)閉彈層,顯示數(shù)據(jù)
                        if(res.data.code == 20031){
                            this.dialogFormVisible4Edit = false;
                            this.$message.success("修改成功");
                        }else if(res.data.code == 20030){
                            this.$message.error("修改失敗");
                        }else{
                            this.$message.error(res.data.msg);
                        }
                    }).finally(()=>{
                        this.getAll();
                    });
                },

                // 刪除
                handleDelete(row) {
                    //1.彈出提示框
                    this.$confirm("此操作永久刪除當(dāng)前數(shù)據(jù),是否繼續(xù)?","提示",{
                        type:'info'
                    }).then(()=>{
                        //2.做刪除業(yè)務(wù)
                        axios.delete("/books/"+row.id).then((res)=>{
                            if(res.data.code == 20021){
                                this.$message.success("刪除成功");
                            }else{
                                this.$message.error("刪除失敗");
                            }
                        }).finally(()=>{
                            this.getAll();
                        });
                    }).catch(()=>{
                        //3.取消刪除
                        this.$message.info("取消刪除操作");
                    });
                }
            }
        })

    </script>

</html>

3,攔截器

對(duì)于攔截器這節(jié)的知識(shí),我們需要學(xué)習(xí)如下內(nèi)容:

  • 攔截器概念
  • 入門案例
  • 攔截器參數(shù)
  • 攔截器工作流程分析

1. 攔截器概念

講解攔截器的概念之前,我們先看一張圖:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

(1)瀏覽器發(fā)送一個(gè)請(qǐng)求會(huì)先到Tomcat的web服務(wù)器

(2)Tomcat服務(wù)器接收到請(qǐng)求以后,會(huì)去判斷請(qǐng)求的是靜態(tài)資源還是動(dòng)態(tài)資源

(3)如果是靜態(tài)資源,會(huì)直接到Tomcat的項(xiàng)目部署目錄下去直接訪問

(4)如果是動(dòng)態(tài)資源,就需要交給項(xiàng)目的后臺(tái)代碼進(jìn)行處理

(5)在找到具體的方法之前,我們可以去配置過濾器(可以配置多個(gè)),按照順序進(jìn)行執(zhí)行

(6)然后進(jìn)入到到中央處理器(SpringMVC中的內(nèi)容),SpringMVC會(huì)根據(jù)配置的規(guī)則進(jìn)行攔截

(7)如果滿足規(guī)則,則進(jìn)行處理,找到其對(duì)應(yīng)的controller類中的方法進(jìn)行執(zhí)行,完成后返回結(jié)果

(8)如果不滿足規(guī)則,則不進(jìn)行處理

(9)這個(gè)時(shí)候,如果我們需要在每個(gè)Controller方法執(zhí)行的前后添加業(yè)務(wù),具體該如何來實(shí)現(xiàn)?

這個(gè)就是攔截器要做的事。

  • 攔截器(Interceptor)是一種動(dòng)態(tài)攔截方法調(diào)用的機(jī)制,在SpringMVC中動(dòng)態(tài)攔截控制器方法的執(zhí)行
  • 作用:
    • 在指定的方法調(diào)用前后執(zhí)行預(yù)先設(shè)定的代碼
    • 阻止原始方法的執(zhí)行
    • 總結(jié):攔截器就是用來做增強(qiáng)

看完以后,大家會(huì)發(fā)現(xiàn)

  • 攔截器和過濾器在作用和執(zhí)行順序上也很相似

所以這個(gè)時(shí)候,就有一個(gè)問題需要思考:攔截器和過濾器之間的區(qū)別是什么?

  • 歸屬不同:Filter屬于Servlet技術(shù),Interceptor屬于SpringMVC技術(shù)
  • 攔截內(nèi)容不同:Filter對(duì)所有訪問進(jìn)行增強(qiáng),Interceptor僅針對(duì)SpringMVC的訪問進(jìn)行增強(qiáng)

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

2. 攔截器入門案例

1. 環(huán)境準(zhǔn)備
  • 創(chuàng)建一個(gè)Web的Maven項(xiàng)目

  • pom.xml添加SSM整合所需jar包

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.itheima</groupId>
      <artifactId>springmvc_12_interceptor</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <dependencies>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.0</version>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
              <port>80</port>
              <path>/</path>
            </configuration>
          </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
      </build>
    </project>
    
    
  • 創(chuàng)建對(duì)應(yīng)的配置類

    public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
        protected Class<?>[] getRootConfigClasses() {
            return new Class[0];
        }
    
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{SpringMvcConfig.class};
        }
    
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        //亂碼處理
        @Override
        protected Filter[] getServletFilters() {
            CharacterEncodingFilter filter = new CharacterEncodingFilter();
            filter.setEncoding("UTF-8");
            return new Filter[]{filter};
        }
    }
    
    @Configuration
    @ComponentScan({"com.itheima.controller"})
    @EnableWebMvc
    public class SpringMvcConfig{
       
    }
    
  • 創(chuàng)建模型類Book

    public class Book {
        private String name;
        private double price;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Book{" +
                    "書名='" + name + '\'' +
                    ", 價(jià)格=" + price +
                    '}';
        }
    }
    
  • 編寫Controller

    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @PostMapping
        public String save(@RequestBody Book book){
            System.out.println("book save..." + book);
            return "{'module':'book save'}";
        }
    
        @DeleteMapping("/{id}")
        public String delete(@PathVariable Integer id){
            System.out.println("book delete..." + id);
            return "{'module':'book delete'}";
        }
    
        @PutMapping
        public String update(@RequestBody Book book){
            System.out.println("book update..."+book);
            return "{'module':'book update'}";
        }
    
        @GetMapping("/{id}")
        public String getById(@PathVariable Integer id){
            System.out.println("book getById..."+id);
            return "{'module':'book getById'}";
        }
    
        @GetMapping
        public String getAll(){
            System.out.println("book getAll...");
            return "{'module':'book getAll'}";
        }
    }
    

最終創(chuàng)建好的項(xiàng)目結(jié)構(gòu)如下:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

2. 攔截器開發(fā)
步驟1:創(chuàng)建攔截器類

讓類實(shí)現(xiàn)HandlerInterceptor接口,重寫接口中的三個(gè)方法。

@Component
//定義攔截器類,實(shí)現(xiàn)HandlerInterceptor接口
//注意當(dāng)前類必須受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {
    @Override
    //原始方法調(diào)用前執(zhí)行的內(nèi)容
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...");
        return true;
    }

    @Override
    //原始方法調(diào)用后執(zhí)行的內(nèi)容
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

    @Override
    //原始方法調(diào)用完成后執(zhí)行的內(nèi)容
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

注意: 攔截器類要被SpringMVC容器掃描到。

步驟2:配置攔截器類
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        //配置攔截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books" );
    }
}
步驟3:SpringMVC添加SpringMvcSupport包掃描
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig{
   
}
步驟4:運(yùn)行程序測(cè)試

使用PostMan發(fā)送http://localhost/books

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

如果發(fā)送http://localhost/books/100會(huì)發(fā)現(xiàn)攔截器沒有被執(zhí)行,原因是攔截器的addPathPatterns方法配置的攔截路徑是/books,我們現(xiàn)在發(fā)送的是/books/100,所以沒有匹配上,因此沒有攔截,攔截器就不會(huì)執(zhí)行。

步驟5:修改攔截器攔截規(guī)則
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        //配置攔截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*" );
    }
}

這個(gè)時(shí)候,如果再次訪問http://localhost/books/100,攔截器就會(huì)被執(zhí)行。

最后說一件事,就是攔截器中的preHandler方法,如果返回true,則代表放行,會(huì)執(zhí)行原始Controller類中要請(qǐng)求的方法,如果返回false,則代表攔截,后面的就不會(huì)再執(zhí)行了。

步驟6:簡(jiǎn)化SpringMvcSupport的編寫
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//實(shí)現(xiàn)WebMvcConfigurer接口可以簡(jiǎn)化開發(fā),但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //配置多攔截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
    }
}

此后咱們就不用再寫SpringMvcSupport類了。

最后我們來看下攔截器的執(zhí)行流程:

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

當(dāng)有攔截器后,請(qǐng)求會(huì)先進(jìn)入preHandle方法,

? 如果方法返回true,則放行繼續(xù)執(zhí)行后面的handle[controller的方法]和后面的方法

? 如果返回false,則直接跳過后面方法的執(zhí)行。

3. 攔截器參數(shù)

1. 前置處理方法

原始方法之前運(yùn)行preHandle

public boolean preHandle(HttpServletRequest request,
                         HttpServletResponse response,
                         Object handler) throws Exception {
    System.out.println("preHandle");
    return true;
}
  • request:請(qǐng)求對(duì)象
  • response:響應(yīng)對(duì)象
  • handler:被調(diào)用的處理器對(duì)象,本質(zhì)上是一個(gè)方法對(duì)象,對(duì)反射中的Method對(duì)象進(jìn)行了再包裝

使用request對(duì)象可以獲取請(qǐng)求數(shù)據(jù)中的內(nèi)容,如獲取請(qǐng)求頭的Content-Type

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String contentType = request.getHeader("Content-Type");
    System.out.println("preHandle..."+contentType);
    return true;
}

使用handler參數(shù),可以獲取方法的相關(guān)信息

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    HandlerMethod hm = (HandlerMethod)handler;
    String methodName = hm.getMethod().getName();//可以獲取方法的名稱
    System.out.println("preHandle..."+methodName);
    return true;
}
2. 后置處理方法

原始方法運(yùn)行后運(yùn)行,如果原始方法被攔截,則不執(zhí)行

public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    System.out.println("postHandle");
}

前三個(gè)參數(shù)和上面的是一致的。

modelAndView:如果處理器執(zhí)行完成具有返回結(jié)果,可以讀取到對(duì)應(yīng)數(shù)據(jù)與頁(yè)面信息,并進(jìn)行調(diào)整

因?yàn)樵蹅儸F(xiàn)在都是返回json數(shù)據(jù),所以該參數(shù)的使用率不高。

3. 完成處理方法

攔截器最后執(zhí)行的方法,無(wú)論原始方法是否執(zhí)行

public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) throws Exception {
    System.out.println("afterCompletion");
}

前三個(gè)參數(shù)與上面的是一致的。

ex:如果處理器執(zhí)行過程中出現(xiàn)異常對(duì)象,可以針對(duì)異常情況進(jìn)行單獨(dú)處理

因?yàn)槲覀儸F(xiàn)在已經(jīng)有全局異常處理器類,所以該參數(shù)的使用率也不高。

這三個(gè)方法中,最常用的是preHandle,在這個(gè)方法中可以通過返回值來決定是否要進(jìn)行放行,我們可以把業(yè)務(wù)邏輯放在該方法中,如果滿足業(yè)務(wù)則返回true放行,不滿足則返回false攔截。

4. 攔截器鏈配置

目前,我們?cè)陧?xiàng)目中只添加了一個(gè)攔截器,如果有多個(gè),該如何配置?配置多個(gè)后,執(zhí)行順序是什么?

1. 配置多個(gè)攔截器
步驟1:創(chuàng)建攔截器類

實(shí)現(xiàn)接口,并重寫接口中的方法

@Component
public class ProjectInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...222");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...222");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...222");
    }
}
步驟2:配置攔截器類
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//實(shí)現(xiàn)WebMvcConfigurer接口可以簡(jiǎn)化開發(fā),但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ProjectInterceptor projectInterceptor;
    @Autowired
    private ProjectInterceptor2 projectInterceptor2;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //配置多攔截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
        registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*");
    }
}

步驟3:運(yùn)行程序,觀察順序

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

攔截器執(zhí)行的順序是和配置順序有關(guān)。就和前面所提到的運(yùn)維人員進(jìn)入機(jī)房的案例,先進(jìn)后出。

  • 當(dāng)配置多個(gè)攔截器時(shí),形成攔截器鏈
  • 攔截器鏈的運(yùn)行順序參照攔截器添加順序?yàn)闇?zhǔn)
  • 當(dāng)攔截器中出現(xiàn)對(duì)原始處理器的攔截,后面的攔截器均終止運(yùn)行
  • 當(dāng)攔截器運(yùn)行中斷,僅運(yùn)行配置在前面的攔截器的afterCompletion操作

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

preHandle:與配置順序相同,必定運(yùn)行

postHandle:與配置順序相反,可能不運(yùn)行

afterCompletion:與配置順序相反,可能不運(yùn)行。

這個(gè)順序不太好記,最終只需要把握住一個(gè)原則即可:以最終的運(yùn)行結(jié)果為準(zhǔn)

筆記來自:黑馬程序員SSM框架教程

4,圖書推薦

本書專門為想要入行從事產(chǎn)品經(jīng)理相關(guān)工作的零基礎(chǔ)就業(yè)人員而編寫,涵蓋了在產(chǎn)品準(zhǔn)備階段、產(chǎn)品開發(fā)階段、產(chǎn)品測(cè)試階段和產(chǎn)品上線后產(chǎn)品經(jīng)理所需要具備的各項(xiàng)基本技能。
全書共分為9章,第1章大致認(rèn)識(shí)產(chǎn)品經(jīng)理的職能范圍;第2章講解了產(chǎn)品經(jīng)理的工作職責(zé);第3章講解了需求的相關(guān)知識(shí);第4章介紹了流程的相關(guān)知識(shí);第5章展示了結(jié)構(gòu)圖;第6章詳細(xì)闡述了界面原型的相關(guān)知識(shí);第7章介紹了UML圖;第8章介紹了PRD文檔的相關(guān)知識(shí);第9章介紹了軟件測(cè)試的相關(guān)知識(shí)。
本書適合零基礎(chǔ)想要入門產(chǎn)品經(jīng)理、產(chǎn)品規(guī)劃師、需求分析師的人員閱讀,也適合用戶體驗(yàn)、市場(chǎng)運(yùn)營(yíng)等相關(guān)部門的朋友,特別是互聯(lián)網(wǎng)、軟件行業(yè)、AI開發(fā)行業(yè)的人員閱讀,還適合大專院校互聯(lián)網(wǎng)和產(chǎn)品開發(fā)相關(guān)專業(yè)的老師和學(xué)生閱讀。

【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器

??本次送 5本書 ,從評(píng)論區(qū)抽5位小伙伴??
活動(dòng)時(shí)間:截止到 2023-06-23 20:00:00
抽獎(jiǎng)方式:利用程序進(jìn)行抽獎(jiǎng)。
參與方式:關(guān)注博主、點(diǎn)贊、收藏,進(jìn)行優(yōu)質(zhì)評(píng)論

?? 獲獎(jiǎng)名單??
釉色清風(fēng)
在努力的前端小白
冰.封萬(wàn)里
韓楚風(fēng)
萬(wàn)物皆可der
名單公布時(shí)間: 2023-06-23 20:00:00文章來源地址http://www.zghlxwxcb.cn/news/detail-500841.html

到了這里,關(guān)于【SpringMVC】統(tǒng)一異常處理 前后臺(tái)協(xié)議聯(lián)調(diào) 攔截器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • android 監(jiān)聽app前后臺(tái)切換

    需求是統(tǒng)計(jì)app使用時(shí)長(zhǎng),要求在按home鍵的時(shí)候也算一次完成的使用記錄。剛開始打算采用監(jiān)聽home鍵點(diǎn)擊,尋求的方法是監(jiān)聽系統(tǒng)廣播。 可以實(shí)現(xiàn)監(jiān)聽home鍵被點(diǎn)擊,但有一個(gè)弊端就是點(diǎn)擊home鍵app切換到后臺(tái)后,在使用別的app點(diǎn)擊home鍵 自己的app還是會(huì)收到這個(gè)廣播,因?yàn)檫@是

    2024年02月11日
    瀏覽(24)
  • 如何判斷Android應(yīng)用置于前后臺(tái)

    ? ? ? ? 項(xiàng)目開發(fā)過程中總會(huì)遇到判斷應(yīng)用程序是否置于后臺(tái)或者從后臺(tái)切換到前臺(tái)。往往在切換的時(shí)候應(yīng)用會(huì)通過請(qǐng)求接口更新頁(yè)面展示數(shù)據(jù)或者提示廣告信息等相關(guān)操作。因此對(duì)于開發(fā)者來說判斷應(yīng)用程序前后臺(tái)狀態(tài)還是比較重要的。下面記錄兩種判斷應(yīng)用前后臺(tái)狀態(tài)的

    2024年02月12日
    瀏覽(28)
  • springmvc統(tǒng)一異常處理攔截器

    使用@RestControllerAdvice+@ExceptionHandler實(shí)現(xiàn) 也可以使用@ControllerAdvice+@ResponseBody+@ExceptionHandler實(shí)現(xiàn) 創(chuàng)建一個(gè)異常處理的類,放在config包下 ?組件類: ?也可以讓不同的異常返回不同的結(jié)果,捕獲什么異常由@ExceptionHandler的value屬性決定,傳入一個(gè)類對(duì)象(可以通過反射獲得) ?

    2024年02月15日
    瀏覽(23)
  • 一個(gè)面向MCU的小型前后臺(tái)系統(tǒng)

    一個(gè)面向MCU的小型前后臺(tái)系統(tǒng)

    JxOS面向MCU的小型前后臺(tái)系統(tǒng),提供消息、事件等服務(wù),以及軟件定時(shí)器,低功耗管理,按鍵,led等常用功能模塊。 gitee倉(cāng)庫(kù)地址為(復(fù)制到瀏覽器打開): 在此基礎(chǔ)上實(shí)現(xiàn)了基于433的簡(jiǎn)單無(wú)線網(wǎng)絡(luò)功能。 此項(xiàng)目的 設(shè)計(jì)思想 是:功能模塊與硬件高度解耦,提高代碼模塊的可

    2024年02月09日
    瀏覽(19)
  • 【jenkins部署】一文弄懂自動(dòng)打包部署(前后臺(tái))

    【jenkins部署】一文弄懂自動(dòng)打包部署(前后臺(tái))

    軟件開發(fā)中,會(huì)分多個(gè)環(huán)境,開發(fā)環(huán)境、測(cè)試環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境,軟件部署如果是純?nèi)斯ひ粋€(gè)個(gè)通過jar的方式, 會(huì)有如下問題: 服務(wù)器過多,容易出錯(cuò) 修改配置,可能會(huì)存在未修改到位的情況 服務(wù)器部署權(quán)限一般只有開發(fā)服務(wù)器人才有權(quán)限,涉及到服務(wù)器的安全

    2024年02月08日
    瀏覽(23)
  • 大文件分片上傳的實(shí)現(xiàn)【前后臺(tái)完整版】

    在一般的產(chǎn)品開發(fā)過程中,大家多少會(huì)遇到上傳視頻功能的需求,往往我們采用的都是對(duì)視頻大小進(jìn)行限制等方法,來防止上傳請(qǐng)求超時(shí),導(dǎo)致上傳失敗。這時(shí)候可能將視頻分片上傳可以對(duì)你的項(xiàng)目有一個(gè)小小的體驗(yàn)優(yōu)化。 本片文章前端是vue,后臺(tái)基于PHP進(jìn)行的分片上傳,需

    2024年02月10日
    瀏覽(22)
  • centos配置nginx+node前后臺(tái)+mongodb

    centos 環(huán)境下安裝

    2024年02月11日
    瀏覽(23)
  • 前后臺(tái)傳遞參數(shù)中出現(xiàn)+、-、=、%、&、#、空格等字符的解決思路

    一、描述問題 前后臺(tái)傳輸數(shù)據(jù)多樣化,可能會(huì)出現(xiàn)特殊字符的情況,比如傳遞的參數(shù)中含有+、空格、=、%等字符,遇到這樣的情況我們?cè)撊绾谓鉀Q呢? 二、問題分析 前后臺(tái)特殊字符對(duì)其編碼,原因可能是這些特殊字符對(duì)于前后臺(tái)傳遞參數(shù)的時(shí)候,有其特殊的用途,比如url中

    2024年01月17日
    瀏覽(20)
  • 一套前后臺(tái)全部開源的H5商城送給大家

    博主給大家推薦一套全部開源的H5電商項(xiàng)目 waynboot-mall 。由博主在2020年開發(fā)至今,已有三年之久。那時(shí)候網(wǎng)上很多的H5商城項(xiàng)目都是半開源版本,要么沒有H5前端代碼,要么需要加群咨詢,屬實(shí)惡心。于是博主決定自己開發(fā)一套完整的移動(dòng)端H5商城,包含一個(gè)管理后臺(tái)、一個(gè)前

    2024年02月02日
    瀏覽(23)
  • 基于springBoot + Vue電影售票系統(tǒng)分前后臺(tái)【完整源碼+數(shù)據(jù)庫(kù)】

    基于springBoot + Vue電影售票系統(tǒng)分前后臺(tái)【完整源碼+數(shù)據(jù)庫(kù)】

    本項(xiàng)目是一套基于springBoot + Vue的電影售票系統(tǒng),主要針對(duì)計(jì)算機(jī)相關(guān)專業(yè)的正在做bishe的學(xué)生和需要項(xiàng)目實(shí)戰(zhàn)練習(xí)的Java學(xué)習(xí)者。 包含:項(xiàng)目源碼、數(shù)據(jù)庫(kù)腳本等,該項(xiàng)目可以直接作為bishe使用。 項(xiàng)目都經(jīng)過嚴(yán)格調(diào)試,確保可以運(yùn)行! 后端:SpringBoot+Mysql+MyBatis+maven 前端:Vu

    2024年02月03日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包