springMVC 的工作原理和機制

qq_duhai發表於2018-03-09
SpringMVC工作原理

 


工作原理
上面的是springMVC的工作原理圖:

1、客戶端發出一個http請求給web伺服器,web伺服器對http請求進行解析,如果匹配DispatcherServlet的請求對映路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet.

2、DipatcherServlet接收到這個請求之後將根據請求的資訊(包括URL、Http方法、請求報文頭和請求引數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。

3-4、DispatcherServlet根據HandlerMapping找到對應的Handler,將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的HandlerAdapter對Handler進行具體的呼叫。

5、Handler對資料處理完成以後將返回一個ModelAndView()物件給DispatcherServlet。

6、Handler返回的ModelAndView()只是一個邏輯檢視並不是一個正式的檢視,DispatcherSevlet通過ViewResolver將邏輯檢視轉化為真正的檢視View。

7、Dispatcher通過model解析出ModelAndView()中的引數進行解析最終展現出完整的view並返回給客戶端。

 

工作機制是什麼

Control的呼叫(續)

接著對於(二)的補充:主要是小結下Control的處理邏輯的關鍵操作;

對於control的處理關鍵就是:DispatcherServlet的handlerMappings集合中根據請求的URL匹配每一個handlerMapping物件中的某個handler,匹配成功之後將會返回這個handler的處理連線handlerExecutionChain物件。而這個handlerExecutionChain物件中將會包含使用者自定義的多個handlerInterceptor物件。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
     * Return the HandlerExecutionChain for this request.
     * <p>Tries all handler mappings in order.
     * @param request current HTTP request
     * @return the HandlerExecutionChain, or <code>null</code> if no handler could be found
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

而對於handlerInterceptor介面中定義的三個方法中,preHandler和postHandler分別在handler的執行前和執行後執行,afterCompletion在view渲染完成、在DispatcherServlet返回之前執行。

 

PS:這麼我們需要注意的是:當preHandler返回false時,當前的請求將在執行完afterCompletion後直接返回,handler也將不會執行。

在類HandlerExecutionChain中的getHandler()方法是返回object物件的;

 

1
2
3
4
5
6
7
/**
     * Return the handler object to execute.
     * @return the handler object
     */
    public Object getHandler() {
        return this.handler;
    }

這裡的handler是沒有型別的,handler的型別是由handlerAdapter決定的。dispatcherServlet會根據handler物件在其handlerAdapters集合中匹配哪個HandlerAdapter例項支援該物件。接下來去執行handler物件的相應方法了,如果該handler物件的相應方法返回一個ModelAndView物件接下來就是去執行View渲染了。

 

 

1
2
3
4
5
6
7
/**
     * Return the handler object to execute.
     * @return the handler object
     */
    public Object getHandler() {
        return this.handler;
    }

 

---------------------------------------邪惡的分割線---------------------------------------------

Model設計

如果handler兌現返回了ModelAndView物件,那麼說明Handler需要傳一個Model例項給view去渲染模版。除了渲染頁面需要model例項,在業務邏輯層通常也有Model例項。

 

ModelAndView物件是連線業務邏輯層與view展示層的橋樑,對spring MVC來說它也是連線Handler與view的橋樑。ModelAndView物件顧名思義會持有一個ModelMap物件和一個View物件或者View的名稱。ModelMap物件就是執行模版渲染時候所需要的變數對應的例項,如jsp的通過request.getAttribute(String)獲取的JSTL標籤名對應的物件。velocity中context.get(String)獲取$foo對應的變數例項。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ModelAndView {
 
/** View instance or view name String */
    private Object view;
 
    /** Model Map */
    private ModelMap model;
 
    /** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
    private boolean cleared = false;
 
.....
 
}

 

ModelMap其實也是一個Map,Handler中將模版中需要的物件存在這個Map中,然後傳遞到view對應的ViewResolver中。

 

1
2
3
4
public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;
 
}

 

不同的ViewResolver會對這個Map中的物件有不同的處理方式;

 

  • velocity中將這個Map儲存到VelocityContext中。
  • JSP中將每一個ModelMap中的元素分別設定到request.setAttribute(modelName,modelValue);

-----------------------邪惡的分割線-----------------------------------------------

view設計

在spring MVC中,view模組需要兩個元件來支援:RequestToViewNameTranslator和ViewResolver

 

1
2
3
4
5
6
7
8
9
10
11
12
public interface RequestToViewNameTranslator {
 
    /**
     * Translate the given {@link HttpServletRequest} into a view name.
     * @param request the incoming {@link HttpServletRequest} providing
     * the context from which a view name is to be resolved
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation fails
     */
    String getViewName(HttpServletRequest request) throws Exception;
 
}

對於 ViewResolver,前面有寫到了,就不寫了;

 

-----------------------邪惡的分割線-------------------------------------------------

RequestToViewNameTranslator:主要支援使用者自定義對viewName的解析,如將請求的ViewName加上字首或者字尾,或者替換成特定的字串等。

ViewResolver:主要是根據使用者請求的viewName建立適合的模版引擎來渲染最終的頁面,ViewResolver會根據viewName建立一個view物件,呼叫view物件的Void render方法渲染出頁面;

 

1
2
3
public interface View {
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}

下面來總結下 Spring MVC解析View的邏輯:

 

 

  • dispatcherServlet方法呼叫getDefaultViewName()方法;

 

 

1
2
3
4
5
6
7
8
9
/**
     * Translate the supplied request into a default view name.
     * @param request current HTTP servlet request
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation failed
     */
    protected String getDefaultViewName(HttpServletRequest request) throws Exception {
        return this.viewNameTranslator.getViewName(request);
    }
  • 呼叫了RequestToViewNameTranslator的getViewName方法;

 

1
2
3
4
5
6
7
8
9
10
11
12
public interface RequestToViewNameTranslator {
 
    /**
     * Translate the given {@link HttpServletRequest} into a view name.
     * @param request the incoming {@link HttpServletRequest} providing
     * the context from which a view name is to be resolved
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation fails
     */
    String getViewName(HttpServletRequest request) throws Exception;
 
}

 

 

 

  • 呼叫LocaleResolver介面的resolveLocale方法;

 

 

1
Locale resolveLocale(HttpServletRequest request);
  • 呼叫ViewResolver介面的resolveViewName方法,返回view物件

 

 

1
View resolveViewName(String viewName, Locale locale) throws Exception;
  • 呼叫render方法渲染出頁面
2016-03-11 12:05 by 孤鴻子, 86344 閱讀, 0 評論, 收藏編輯

SpringMVC工作原理

 


工作原理
上面的是springMVC的工作原理圖:

1、客戶端發出一個http請求給web伺服器,web伺服器對http請求進行解析,如果匹配DispatcherServlet的請求對映路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet.

2、DipatcherServlet接收到這個請求之後將根據請求的資訊(包括URL、Http方法、請求報文頭和請求引數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。

3-4、DispatcherServlet根據HandlerMapping找到對應的Handler,將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的HandlerAdapter對Handler進行具體的呼叫。

5、Handler對資料處理完成以後將返回一個ModelAndView()物件給DispatcherServlet。

6、Handler返回的ModelAndView()只是一個邏輯檢視並不是一個正式的檢視,DispatcherSevlet通過ViewResolver將邏輯檢視轉化為真正的檢視View。

7、Dispatcher通過model解析出ModelAndView()中的引數進行解析最終展現出完整的view並返回給客戶端。

 

工作機制是什麼

Control的呼叫(續)

接著對於(二)的補充:主要是小結下Control的處理邏輯的關鍵操作;

對於control的處理關鍵就是:DispatcherServlet的handlerMappings集合中根據請求的URL匹配每一個handlerMapping物件中的某個handler,匹配成功之後將會返回這個handler的處理連線handlerExecutionChain物件。而這個handlerExecutionChain物件中將會包含使用者自定義的多個handlerInterceptor物件。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
     * Return the HandlerExecutionChain for this request.
     * <p>Tries all handler mappings in order.
     * @param request current HTTP request
     * @return the HandlerExecutionChain, or <code>null</code> if no handler could be found
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

而對於handlerInterceptor介面中定義的三個方法中,preHandler和postHandler分別在handler的執行前和執行後執行,afterCompletion在view渲染完成、在DispatcherServlet返回之前執行。

 

PS:這麼我們需要注意的是:當preHandler返回false時,當前的請求將在執行完afterCompletion後直接返回,handler也將不會執行。

在類HandlerExecutionChain中的getHandler()方法是返回object物件的;

 

1
2
3
4
5
6
7
/**
     * Return the handler object to execute.
     * @return the handler object
     */
    public Object getHandler() {
        return this.handler;
    }

這裡的handler是沒有型別的,handler的型別是由handlerAdapter決定的。dispatcherServlet會根據handler物件在其handlerAdapters集合中匹配哪個HandlerAdapter例項支援該物件。接下來去執行handler物件的相應方法了,如果該handler物件的相應方法返回一個ModelAndView物件接下來就是去執行View渲染了。

 

 

1
2
3
4
5
6
7
/**
     * Return the handler object to execute.
     * @return the handler object
     */
    public Object getHandler() {
        return this.handler;
    }

 

---------------------------------------邪惡的分割線---------------------------------------------

Model設計

如果handler兌現返回了ModelAndView物件,那麼說明Handler需要傳一個Model例項給view去渲染模版。除了渲染頁面需要model例項,在業務邏輯層通常也有Model例項。

 

ModelAndView物件是連線業務邏輯層與view展示層的橋樑,對spring MVC來說它也是連線Handler與view的橋樑。ModelAndView物件顧名思義會持有一個ModelMap物件和一個View物件或者View的名稱。ModelMap物件就是執行模版渲染時候所需要的變數對應的例項,如jsp的通過request.getAttribute(String)獲取的JSTL標籤名對應的物件。velocity中context.get(String)獲取$foo對應的變數例項。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ModelAndView {
 
/** View instance or view name String */
    private Object view;
 
    /** Model Map */
    private ModelMap model;
 
    /** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
    private boolean cleared = false;
 
.....
 
}

 

ModelMap其實也是一個Map,Handler中將模版中需要的物件存在這個Map中,然後傳遞到view對應的ViewResolver中。

 

1
2
3
4
public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;
 
}

 

不同的ViewResolver會對這個Map中的物件有不同的處理方式;

 

  • velocity中將這個Map儲存到VelocityContext中。
  • JSP中將每一個ModelMap中的元素分別設定到request.setAttribute(modelName,modelValue);

-----------------------邪惡的分割線-----------------------------------------------

view設計

在spring MVC中,view模組需要兩個元件來支援:RequestToViewNameTranslator和ViewResolver

 

1
2
3
4
5
6
7
8
9
10
11
12
public interface RequestToViewNameTranslator {
 
    /**
     * Translate the given {@link HttpServletRequest} into a view name.
     * @param request the incoming {@link HttpServletRequest} providing
     * the context from which a view name is to be resolved
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation fails
     */
    String getViewName(HttpServletRequest request) throws Exception;
 
}

對於 ViewResolver,前面有寫到了,就不寫了;

 

-----------------------邪惡的分割線-------------------------------------------------

RequestToViewNameTranslator:主要支援使用者自定義對viewName的解析,如將請求的ViewName加上字首或者字尾,或者替換成特定的字串等。

ViewResolver:主要是根據使用者請求的viewName建立適合的模版引擎來渲染最終的頁面,ViewResolver會根據viewName建立一個view物件,呼叫view物件的Void render方法渲染出頁面;

 

1
2
3
public interface View {
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}

下面來總結下 Spring MVC解析View的邏輯:

 

 

  • dispatcherServlet方法呼叫getDefaultViewName()方法;

 

 

1
2
3
4
5
6
7
8
9
/**
     * Translate the supplied request into a default view name.
     * @param request current HTTP servlet request
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation failed
     */
    protected String getDefaultViewName(HttpServletRequest request) throws Exception {
        return this.viewNameTranslator.getViewName(request);
    }
  • 呼叫了RequestToViewNameTranslator的getViewName方法;

 

1
2
3
4
5
6
7
8
9
10
11
12
public interface RequestToViewNameTranslator {
 
    /**
     * Translate the given {@link HttpServletRequest} into a view name.
     * @param request the incoming {@link HttpServletRequest} providing
     * the context from which a view name is to be resolved
     * @return the view name (or <code>null</code> if no default found)
     * @throws Exception if view name translation fails
     */
    String getViewName(HttpServletRequest request) throws Exception;
 
}

 

 

 

  • 呼叫LocaleResolver介面的resolveLocale方法;

 

 

1
Locale resolveLocale(HttpServletRequest request);
  • 呼叫ViewResolver介面的resolveViewName方法,返回view物件

 

 

1
View resolveViewName(String viewName, Locale locale) throws Exception;
  • 呼叫render方法渲染出頁面

相關文章