Spring MVC 面試題
- Spring MVC 面試題
- 簡單介紹一下 Spring MVC 框架
- Spring MVC 有什麼優點?
- 描述一下 Spring MVC 的工作流程
- 簡單介紹 Spring MVC 的核心元件
- @Controller 註解有什麼用?
- @RequestMapping 註解有什麼用?
- @RestController 和 @Controller 有什麼區別?
- @RequestMapping 和 @GetMapping 註解的不同之處在哪裡?
- @RequestParam 和 @PathVariable 兩個註解的區別
- 返回 JSON 格式使用什麼註解?
- 介紹一下 Spring MVC 中的 WebApplicationContext ?
- Spring MVC 和 Struts2 的異同?
- 介紹下 Spring MVC 攔截器?
- Spring MVC 的攔截器和 Filter 過濾器有什麼差別?
- REST 面試題
簡單介紹一下 Spring MVC 框架
在早期 Java Web 的開發中,統一把顯示層、控制層、顯示層的操作全部交給 JSP 或者 Java Bean 來進行處理,存在一定的弊端,例如:JSP 和 Java Bean 之間嚴重耦合、開發效率低等弊端。
Spring MVC 是 Spring 體系中的一員,提供“模型-檢視-控制器”(Model-View-Controller)架構和隨時可用的元件,用於開發靈活且鬆散耦合的 Web 應用程式。
MVC 模式有助於分離應用程式的不同方面,如輸入邏輯,業務邏輯和 UI 邏輯,同時在所有這些元素之間提供鬆散耦合。
Spring MVC 有什麼優點?
- 使用真的非常方便,無論是新增 HTTP 請求方法對映的方法,還是不同資料格式的響應。
- 提供攔截器機制,可以方便的對請求進行攔截處理。
- 提供異常機制,可以方便的對異常做統一處理。
- 可以任意使用各種檢視技術,而不僅僅侷限於 JSP ,例如 Freemarker、Thymeleaf 等等。
描述一下 Spring MVC 的工作流程
Spring MVC 也是基於 Servlet 來處理請求的,主要通過 DispatcherServlet 這個 Servlet 來處理請求,處理過程需要通過九大元件來完成,先看到下面這個流程圖:
Spring MVC 處理請求的流程大致如上圖所示
- 使用者的瀏覽器傳送一個請求,這個請求經過網際網路到達了我們的伺服器。Servlet 容器首先接待了這個請求,並將該請求委託給
DispatcherServlet
進行處理。 DispatcherServlet
將該請求傳給了處理器對映元件HandlerMapping
,並獲取到適合該請求的 HandlerExecutionChain 攔截器和處理器物件。- 在獲取到處理器後,
DispatcherServlet
還不能直接呼叫處理器的邏輯,需要進行對處理器進行適配。處理器適配成功後,DispatcherServlet
通過處理器介面卡HandlerAdapter
呼叫處理器的邏輯,並獲取返回值ModelAndView
物件。 - 之後,
DispatcherServlet
需要根據 ModelAndView 解析檢視。解析檢視的工作由ViewResolver
完成,若能解析成功,ViewResolver
會返回相應的 View 檢視物件。 - 在獲取到具體的 View 物件後,最後一步要做的事情就是由 View 渲染檢視,並將渲染結果返回給使用者。
以上就是 Spring MVC 處理請求的全過程,上面的流程進行了一定的簡化,主要涉及到最核心的元件,還有許多其他元件沒有表現出來,不過這並不影響大家對主過程的理解。
總結:客戶端發起請求後,最終會交由 DispatcherServlet 來處理,它會通過你的 URI 找到對應的方法,從請求中解析引數,然後通過反射機制呼叫該方法,將方法的執行結果設定到響應中,如果存在對應的 View 物件,則進行頁面渲染,實際上就是將請求轉發到指定的 URL
簡單介紹 Spring MVC 的核心元件
那麼接下來就簡單介紹一下 DispatcherServlet
和九大元件(按使用順序排序的):
元件 | 說明 |
---|---|
DispatcherServlet | Spring MVC 的核心元件,是請求的入口,負責協調各個元件工作 |
MultipartResolver | 內容型別( Content-Type )為 multipart/* 的請求的解析器,例如解析處理檔案上傳的請求,便於獲取引數資訊以及上傳的檔案 |
HandlerMapping | 請求的處理器匹配器,負責為請求找到合適的 HandlerExecutionChain 處理器執行鏈,包含處理器(handler )和攔截器們(interceptors ) |
HandlerAdapter | 處理器的介面卡。因為處理器 handler 的型別是 Object 型別,需要有一個呼叫者來實現 handler 是怎麼被執行。Spring 中的處理器的實現多變,比如使用者處理器可以實現 Controller 介面、HttpRequestHandler 介面,也可以用 @RequestMapping 註解將方法作為一個處理器等,這就導致 Spring MVC 無法直接執行這個處理器。所以這裡需要一個處理器介面卡,由它去執行處理器 |
HandlerExceptionResolver | 處理器異常解析器,將處理器( handler )執行時發生的異常,解析( 轉換 )成對應的 ModelAndView 結果 |
RequestToViewNameTranslator | 檢視名稱轉換器,用於解析出請求的預設檢視名 |
LocaleResolver | 本地化(國際化)解析器,提供國際化支援 |
ThemeResolver | 主題解析器,提供可設定應用整體樣式風格的支援 |
ViewResolver | 檢視解析器,根據檢視名和國際化,獲得最終的檢視 View 物件 |
FlashMapManager | FlashMap 管理器,負責重定向時,儲存引數至臨時儲存(預設 Session) |
Spring MVC 對各個元件的職責劃分的比較清晰。DispatcherServlet
負責協調,其他元件則各自做分內之事,互不干擾。
@Controller 註解有什麼用?
@Controller
註解標記一個類為 Spring Web MVC 控制器 Controller。Spring MVC 會將掃描到該註解的類,然後掃描這個類下面帶有 @RequestMapping
註解的方法,根據註解資訊,為這個方法生成一個對應的處理器物件,在上面的 HandlerMapping 和 HandlerAdapter元件中講到過。
當然,除了新增 @Controller
註解這種方式以外,你還可以實現 Spring MVC 提供的 Controller
或者 HttpRequestHandler
介面,對應的實現類也會被作為一個處理器物件
@RequestMapping 註解有什麼用?
@RequestMapping
註解,在上面已經講過了,配置處理器的 HTTP 請求方法,URI等資訊,這樣才能將請求和方法進行對映。這個註解可以作用於類上面,也可以作用於方法上面,在類上面一般是配置這個控制器的 URI 字首
@RestController 和 @Controller 有什麼區別?
@RestController
註解,在 @Controller
基礎上,增加了 @ResponseBody
註解,更加適合目前前後端分離的架構下,提供 Restful API ,返回例如 JSON 資料格式。當然,返回什麼樣的資料格式,根據客戶端的 ACCEPT
請求頭來決定。
@RequestMapping 和 @GetMapping 註解的不同之處在哪裡?
-
@RequestMapping
:可註解在類和方法上;@GetMapping
僅可註冊在方法上 -
@RequestMapping
:可進行 GET、POST、PUT、DELETE 等請求方法;@GetMapping
是@RequestMapping
的 GET 請求方法的特例,目的是為了提高清晰度。
@RequestParam 和 @PathVariable 兩個註解的區別
兩個註解都用於方法引數,獲取引數值的方式不同,@RequestParam
註解的引數從請求攜帶的引數中獲取,而 @PathVariable
註解從請求的 URI 中獲取
返回 JSON 格式使用什麼註解?
可以使用 @ResponseBody
註解,或者使用包含 @ResponseBody
註解的 @RestController
註解。
當然,還是需要配合相應的支援 JSON 格式化的 HttpMessageConverter 實現類。例如,Spring MVC 預設使用 MappingJackson2HttpMessageConverter
介紹一下 Spring MVC 中的 WebApplicationContext ?
WebApplicationContext 是實現 ApplicationContext 介面的子類,專門為 WEB 應用準備的
- 它允許從相對於 Web 根目錄的路徑中載入配置檔案,完成初始化 Spring MVC 元件的工作。
- 從 WebApplicationContext 中,可以獲取 ServletContext 引用,整個 Web 應用上下文物件將作為屬性放置在 ServletContext 中,以便 Web 應用環境可以訪問 Spring 上下文。
Spring MVC 和 Struts2 的異同?
入口不同
- Spring MVC 的入門是一個 Servlet 控制器。
- Struts2 入門是一個 Filter 過濾器。
配置對映不同,
- Spring MVC 是基於方法開發,傳遞引數是通過方法形參,一般設定為單例。
- Struts2 是基於類開發,傳遞引數是通過類的屬性,只能設計為多例。
檢視不同
- Spring MVC 通過引數解析器是將 Request 物件內容進行解析成方法形參,將響應資料和頁面封裝成 ModelAndView 物件,最後又將模型資料通過 Request 物件傳輸到頁面。其中,如果檢視使用 JSP 時,預設使用 JSTL 。
- Struts2 採用值棧儲存請求和響應的資料,通過 OGNL 存取資料。
介紹下 Spring MVC 攔截器?
Spring MVC 攔截器有三個增強處理的地方:
- 前置處理:在執行方法前執行,全部成功執行才會往下執行方法
- 後置處理:在成功執行方法後執行,倒序
- 已完成處理:不管方法是否成功執行都會執行,不過只會執行前置處理成功的攔截器,倒序
可以通過攔截器進行許可權檢驗,引數校驗,記錄日誌等操作
Spring MVC 的攔截器和 Filter 過濾器有什麼差別?
有以下幾點:
- 功能相同:攔截器和 Filter 都能實現相應的功能,誰也不比誰強
- 容器不同:攔截器構建在 Spring MVC 體系中;Filter 構建在 Servlet 容器之上
- 使用便利性不同:攔截器提供了三個方法,分別在不同的時機執行;過濾器僅提供一個方法,當然也能實現攔截器的執行時機的效果,就是麻煩一些
一般擴充性好的框架,都會提供相應的攔截器或過濾器機制,方便的開發人員做一些擴充
REST 面試題
REST 代表著什麼?
REST 代表著抽象狀態轉移,它是根據 HTTP 協議從客戶端傳送資料到服務端,例如:服務端的一本書可以以 XML 或 JSON 格式傳遞到客戶端
然而,假如你不熟悉REST,我建議你先看看 REST API design and development 這篇文章來更好的瞭解它。也可以閱讀知乎上的 《怎樣用通俗的語言解釋 REST,以及 RESTful?》 討論
資源是什麼?
資源是指資料在 REST 架構中如何顯示的。將實體作為資源公開 ,它允許客戶端通過 HTTP 方法如:GET, POST,PUT, DELETE 等讀,寫,修改和建立資源
什麼是安全的 REST 操作?
REST 介面是通過 HTTP 方法完成操作
- 一些 HTTP 操作是安全的,如 GET 和 HEAD ,它不能在服務端修改資源
- 換句話說,PUT、POST 和 DELETE 是不安全的,因為他們能修改服務端的資源
所以,是否安全的界限,在於是否修改服務端的資源
什麼是冪等操作? 為什麼冪等操作如此重要?
有一些 HTTP 方法,如:GET,不管你使用多少次它都能產生相同的結果,在沒有任何一邊影響的情況下,傳送多個 GET 請求到相同的URI 將會產生相同的響應結果。因此,這就是所謂冪等操作
換句話說,POST方法不是冪等操作 ,因為如果傳送多個 POST 請求,它將在服務端建立不同的資源。但是,假如你用 PUT 更新資源,它將是冪等操作。
甚至多個 PUT 請求被用來更新服務端資源,將得到相同的結果
REST 是可擴充套件的或說是協同的嗎?
是的,REST 是可擴充套件的和可協作的。它既不託管一種特定的技術選擇,也不定在客戶端或者服務端。你可以用 Java, C++, Python, 或 JavaScript 來建立 RESTful Web 服務,也可以在客戶端使用它們。
我建議你讀一本關於REST介面的書來了解更多,如:RESTful Web Services 。
所以這裡的“可擴充”、“協同”對應到我們平時常說的,“跨語言”、“語言無關”
REST 用哪種 HTTP 方法呢?
REST 能用任何的 HTTP 方法,但是,最受歡迎的是:
- 用 GET 來檢索服務端資源
- 用 POST 來建立服務端資源
- 用 PUT 來更新服務端資源
- 用 DELETE 來刪除服務端資源
恰好,這四個操作,對上我們日常邏輯的 CRUD 操作
刪除的 HTTP 狀態返回碼是什麼 ?
在刪除成功之後,您的 REST API 應該返回什麼狀態程式碼,並沒有嚴格的規則。它可以返回 200 或 204 沒有內容
- 一般來說,如果刪除操作成功,響應主體為空,返回 204
- 如果刪除請求成功且響應體不是空的,則返回 200
REST API 是無狀態的嗎?
是的,REST API 應該是無狀態的,因為它是基於 HTTP 的,它也是無狀態的
REST API 中的請求應該包含處理它所需的所有細節。它不應該依賴於以前或下一個請求或伺服器端維護的一些資料,例如會話
REST 規範為使其無狀態設定了一個約束,在設計 REST API 時,你應該記住這一點
REST安全嗎? 你能做什麼來保護它?
安全是一個寬泛的術語。它可能意味著訊息的安全性,這是通過認證和授權提供的加密或訪問限制提供的
REST 通常不是安全的,需要開發人員自己實現安全機制