Controller是Spring MVC爲咱們提供的基礎的控制器接口,和HttpServlet同樣,接收request和response參數處理用戶請求,並返回ModelAndView,從概念上能夠類比Struts的Action。git
Controller主要實現的以下功能:github
基於Controller開發請求處理Handler的特色:web
就目前項目開發,幾乎不會使用此方式進行開發,除非維護一些歷史項目。目前是基於註解進行開發,從Spring2.5及以後開始支持。編寫本章內容主要是基於知識點的全面性來考慮,你們能夠了解了解。spring
本系列文章是基於Spring5.0.5RELEASE。瀏覽器
Spring提供的Controller接口,定義了一個方法,做用就是處理用戶請求,源碼以下:緩存
package org.springframework.web.servlet.mvc; public interface Controller { /** *接收request和response參數,處理用戶請求 *參數從request中獲取 *方法返回ModelAndView,Model爲模型數據,View爲視圖 */ ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; }
Spring提供了以下實現:session
AbstractController 控制瀏覽器緩存、支持的請求方法等等mvc
ServletForwardingController 將Spring Handler接收的請求轉發給一個Servlet去執行app
ParameterizableViewController 參數化視圖控制器,根據參數的邏輯視圖名直接選擇須要展現的視圖ide
AbstractUrlViewController 根據請求URL路徑直接轉化爲邏輯視圖名的支持基類
UrlFilenameViewController 將請求URL路徑轉換爲邏輯視圖名並返回的實現類ServletWrappingController Servlet包裝控制器
以上是Spring MVC爲咱們提供Controller接口的默認實現,下面咱們接着分析這些實現類。
該抽象類繼承WebContentGenerator並實現Controller接口,其中WebContentGenerator類用於瀏覽器緩存控制、自定義Controller支持的請求方法類型(默認支持:GET/HEAD/POST)等。
WebContentGenerator類的主要屬性以下:
/** 支持的請求方法類型,默認支持:GET、HEAD、POST */ @Nullable private Set<String> supportedMethods; @Nullable private String allowHeader; /** 當前請求是否必須有session */ private boolean requireSession = false; @Nullable private CacheControl cacheControl; /** 緩存過時時間,正數表示須要緩存,負數表示不作任何事情 */ private int cacheSeconds = -1; @Nullable private String[] varyByRequestHeaders; /** 是否使用HTTP1.0協議過時響應頭:若是true則會在響應頭添加「Expires:」;須要配合cacheSeconds使用 */ private boolean useExpiresHeader = false; /** 是否使用HTTP1.1協議的緩存控制響應頭,若是true則會在響應頭添加;須要配合cacheSeconds使用 */ private boolean useCacheControlHeader = true; /** 是否使用HTTP 1.1協議的緩存控制響應頭,若是true則會在響應頭添加;須要配合cacheSeconds使用 */ private boolean useCacheControlNoStore = true;
AbstractController類源碼以下:
/** 表示該控制器是否在執行時同步session,從而保證該會話的用戶串行訪問該控制器 */ private boolean synchronizeOnSession = false; /** *實現Controller接口的handleRequest方法 */ @Override @Nullable public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { if (HttpMethod.OPTIONS.matches(request.getMethod())) { response.setHeader("Allow", getAllowHeader()); return null; } // 檢查是否支持請求方法以及必須的session checkRequest(request); // 根據設置準備response prepareResponse(response); // 若是必要順序執行handleRequestInternal方法 if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { return handleRequestInternal(request, response); } } } return handleRequestInternal(request, response); } /** * 須要子類實現的模板方法 */ @Nullable protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception;
本章實戰是經過繼承AbstractController類編寫用戶請求handler,測試以下幾點:
經過前幾篇及上面的分析,SimpleControllerHandlerAdapter類能夠適配實現了Controller接口的類,AbstractController實現了Controller接口的handleRequest方法,並預留了handleRequestInternal模板方法供子類實現,用戶處理用戶請求,根據這個思路,咱們要使用SimpleControllerHandlerAdapter適配Controller時,只需繼承AbstractController類並實現handleRequestInternal方法便可,具體源碼以下:
自定義Controller源碼:
/** *繼承AbstractController並實現handleRequestInternal方法 */ public class HelloWorldController extends AbstractController { /** *經過response直接回寫數據,也可經過ModelAndView指定邏輯視圖並回寫數據 */ @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { Writer writer = response.getWriter(); writer.write("hello AbstractController"); writer.flush(); return null; } }
配置文件配置以下:
<!-- 使用BeanNameUrlHandlerMapping映射器 能夠不用配置,Spring MVC默認支持:BeanNameUrlHanderMapping、RequestMappingHandlerMapping --> <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 指定Spring使用SimpleControllerHandlerAdapter適配器 能夠不用配置,Spring MVC默認支持:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter --> <bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 配置Controller bean --> <bean name="/helloWorldController" class="com.github.dalianghe.controller.HelloWorldController"/>
驗證結果
代碼編寫完後,啓動應用進行測試,AbstractController默認支持GET、HEAD、POST方法類型,咱們使用Postman進行測試,GET請求結果以下:
HEAD、POST也能處理,但若是發起PUT請求則返回不支持方法類型,以下圖:
AbstractController默認支持GET、HEAD、POST三種請求類型,本例經過設置supportedMethods屬性來設置支持的請求方法類型,代碼以下:
配置文件配置以下:
<!-- 配置Controller bean --> <bean name="/helloWorldController" class="com.github.dalianghe.controller.HelloWorldController"> <!-- 設置支持的請求方法類型,以下支持PUT、POST --> <property name="supportedMethods"> <set> <value>PUT</value> <value>POST</value> </set> </property> </bean>
驗證結果
只需在Controller Bean修改supportMethods屬性接口,測試PUT請求,結果以下:
當把requireSession屬性設置爲true時,訪問Controller需檢查有無session,若是沒有將跑出HttpSessionRequiredException異常,代碼以下:
配置文件配置以下:
<!-- 配置Controller bean --> <bean name="/helloWorldController" class="com.github.dalianghe.controller.HelloWorldController"> <!-- 設置支持的請求方法類型,以下支持PUT、POST --> <property name="supportedMethods"> <set> <value>GET</value> <value>POST</value> </set> </property> <!-- 訪問此處理器前檢查session --> <property name="requireSession" value="true"/> </bean> <!-- 增長一個處理器,用於獲取session --> <bean id="/helloWorld2Controller" class="com.github.dalianghe.controller.HelloWorld2Controller"/>
新增的HelloWorld2Controller與HelloWorldController代碼基礎上增長獲取session的代碼,以下:
request.getSession(true);
測試驗證
首先驗證沒有session狀況下,結果以下:
說明在訪問到自定義Controller前檢查session沒有,拋出HttpSessionRequiredException異常
咱們增長了一個新的controller用於設置建立session,此時咱們訪問一次後,再訪問須要驗證的session的請求,結果以下:
經過結果可見,測試能正常訪問了。
本章主要分析了Controller接口、AbstractController抽象類以及對自定義Controller的幾個重要屬性進行了測試,但願對你們有幫助,謝謝。
最後建立了qq羣方便你們交流,可掃描加入,同時也可加我qq:276420284,共同窗習、共同進步,謝謝!