springMVC 的工作原理和機制


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方法渲染出頁面


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM