關於Filter中ServletRequest強轉HttpServletRequest問題

JiangHe1997發表於2020-11-28

什麼是ServletRequest 和ServletResponse

ServletRequest由Servlet容器來管理,當客戶請求到來時,容器建立一個ServletRequest物件,封裝請求資料,同時建立一個ServletResponse物件,封裝響應資料。這兩個物件將被容器作為service()方法的引數傳遞給Servlet,Servlet利用ServletRequest物件獲取客戶端發來的請求資料,利用ServletResponse物件傳送響應資料。

而在過濾器中有這樣的程式碼:

我們知道我們對子類實現進行向上轉型得到父類物件是安全的,因為子類會完全繼承父類的方法,我們向上轉型為父類,當我們呼叫父類的方法其實在子類實現中是能完全找到的。反之向下轉型是不安全的,我們子類除了完全繼承父類的方法外還會擴充自己的方法,所以我們在呼叫子類方法時可能在父類實現中是找不到的,所以向下轉型不安全。

但是在過濾器中,我們經常這樣使用。這是為何?

HttpServletRequest和ServletRequest都是介面,他們都只是定義了方法卻沒有提供相關實現。所以我們看到的ServletRequest request中的request物件其實並不是我們ServletRequest 的一個具體實現。

這裡主要看request 物件的具體實現類究竟是繼承的哪個介面,如果繼承自HttpServletRequest介面那麼我們向下轉型使用HttpServletRequest介面的方法就是安全的。測試如下:

證明我們的request物件的確是HttpServletRequest的一個例項。

 也就是說doFilter的引數request物件的生成方式不是ServletRequest request = new ServletRequest();這種形式,而是ServletRequest request = new HttpServletRequest();這種形式,引數裡的request不是父類ServletRequest的物件,而是HttpServletRequest的上轉型物件

 再說一下為什麼在Filter裡要強制轉換?

  答:ServletRequest request;這個是將子類物件賦給父類引用,他執行時的型別是子類,編譯時的型別是父類,但是在執行時,父類型別物件呼叫的方法如果子類裡面有,那就執行子類裡面的方法,如果編譯時的型別也就是父類沒有呼叫的那個方法,則報錯。所以在那裡要做一個強制型別轉換,否則就會報錯。

 

 

 

 

 

相關文章