通過自己實現介面來加深理解SpringMVC的執行流程
功能介紹
上篇文章【從原始碼角度瞭解SpringMVC的執行流程】通過介面原始碼向大家介紹了SpringMVC的執行流程,主要偏重於原始碼。這篇檔案我們來自己實現那幾個關鍵介面,來真實體驗下SpringMVC關鍵的流程,以此來加深理解。功能很簡單,通過訪問一個地址 /mymvc 來自動跳轉到工程首頁,但是我們不用SpringMVC自帶的Controller等元件,完全自己手動開發。工程結構如下圖
程式碼流程
將自定義的實現類放入Ioc容器中。
@Configuration public class MyConfig { @Bean public HandlerMapping myHandlerMapping() { return new MyHandlerMapping(); } @Bean public HandlerAdapter myHandlerAdapter() { return new MyHandlerAdapter(); } @Bean public ViewResolver myViewResolver() { return new MyViewResolver(); } }
獲取處理器
獲取實現了HandlerMapping介面的類呼叫getHandler獲取handler。
下面的程式碼是自定義HandlerMapping繼承於AbstractHandlerMapping 。其中AbstractHandlerMapping 實現了HandlerMapping介面。這也是程式碼通常的結構。定義一個介面,抽象類實現介面完善一些基礎程式碼,並將那些可以擴充套件的功能再暴露出去,這樣我們再開發時只需要關注自己擴充套件的功能即可,不需要將介面所有的方法都再實現一遍,大大減少了開發成本。
新建自定義的處理器MyHandler返回。這裡有一點需要注意,就是需要設定排序號,否則SpringMVC會先執行SimpleUrlHandlerMapping,這個類作為SpringMVC中最後執行的類,如果沒有找到處理器,則會返回異常,所以自定義的HandlerMapping排序號必須大於這個類的排序號,先於此類執行。
public class MyHandlerMapping extends AbstractHandlerMapping { @Override protected Object getHandlerInternal(HttpServletRequest request) throws Exception { Object handler = null; String requestUri = getUrlPathHelper().getRequestUri(request); if (requestUri.equals("/mymvc")) { handler = new MyHandler(); } return handler; } @Override public int getOrder() { return 1; } }
獲取處理器對應的介面卡
獲取實現了HandlerAdapter介面的類呼叫supports判斷介面卡是否適配上面獲取的處理器,為什麼會有介面卡這一層邏輯上篇程式碼也介紹過了。
下面程式碼為自定義HandlerAdapter,supports邏輯很簡單,判斷處理器型別是否為MyHandler。
public class MyHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
if (handler instanceof MyHandler) {
return true;
}
return false;
}
介面卡呼叫處理器
呼叫自定義處理器的handler方法,返回邏輯檢視名,並封裝為ModelAndView。
public class MyHandlerAdapter implements HandlerAdapter {
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
MyHandler myHandler = (MyHandler) handler;
String result = myHandler.handler();
ModelAndView mv = new ModelAndView();
mv.setViewName(result);
return mv;
}
自定義處理器,返回 myview 作為邏輯檢視名。
public class MyHandler {
public String handler() {
return "myview";
}
}
解析檢視
判斷邏輯檢視名為 myview 新建檢視返回。
public class MyViewResolver implements ViewResolver {
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
View view = null;
if ("myview".equals(viewName)) {
view = new MyView();
}
return view;
}
}
渲染檢視
直接跳轉到首頁。
public class MyView implements View {
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "http://localhost:8080/";
response.sendRedirect(path);
}
@Override
public String getContentType() {
return "text/html;charset=ISO-8859-1";
}
}
結語
上面程式碼邏輯很簡單,大家也可以照著這個思路自己動手開發自定義的擴充套件功能,自己DUBUG體會一下整體流程,我相信會對SpringMVC的執行流程有個更加具象的理解