1. 程式人生 > >通過自己實現介面來加深理解SpringMVC的執行流程

通過自己實現介面來加深理解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的執行流程有個更加具象的理解