推薦淘寶秋冬男裝熱賣網店

          追求無止境

          我的程序人生
          隨筆 - 31, 文章 - 2, 評論 - 20, 引用 - 0
          數據加載中……

          Spring MVC框架學習筆記 之 View技術

          以前,我們詳細介紹了Spring的Controller技術。Spring的面向接口編程,使Controller的實現多種多樣。View技術也一樣。今天的分析先從在Controller中的ModelAndView開始。

          public class ModelAndView {     
            private Object view; //View實例或者view的字符串    
          /** Model Map */  
            private ModelMap model; //model
           /* * Convenient constructor when there is no model data to expose.     * Can also be used in conjunction with <code>addObject</code>.    
           * @param view View object to render   
            * @see #addObject     */  
           public ModelAndView(View view) {        
              this.view = view;    
          }
          public ModelAndView(String viewName){ 
             this.view = viewName;
          }

           
          可以看到view實例可以指向一個View對象或者字符串。現在先看看View接口:
          public interface View { 
          
              /**
               * Return the content type of the view, if predetermined.
               * <p>Can be used to check the content type upfront,
               * before the actual rendering process.
               * @return the content type String (optionally including a character set),
               * or <code>null</code> if not predetermined.
               */
              String getContentType(); 
          
              /**
               * 繪制視圖
               * 繪制視圖的第一步是準備請求: 如果是JSP的視圖技術
               * 首先會把model設為request的屬性。
               * 第二步則是真正的繪制視圖
               * @param model Map with name Strings as keys and corresponding model
               * objects as values (Map can also be <code>null</code> in case of empty model)
               * @param request current HTTP request
               * @param response HTTP response we are building
               * @throws Exception if rendering failed
               */
              void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; 
          
          }
          在這之后,我們再來看看View的實現繼承類圖,可以看到Spring支持多種類型視圖:

          org.springframework.web.servlet.view.AbstractView (implements org.springframework.beans.factory.BeanNameAware, org.springframework.web.servlet.View)

          • org.springframework.web.servlet.view.document.AbstractExcelView
          • org.springframework.web.servlet.view.document.AbstractJExcelView
          • org.springframework.web.servlet.view.document.AbstractPdfView
          • org.springframework.web.servlet.view.AbstractUrlBasedView (implements org.springframework.beans.factory.InitializingBean)
            • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView
              • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView
                • org.springframework.web.servlet.view.jasperreports.ConfigurableJasperReportsView
                • org.springframework.web.servlet.view.jasperreports.JasperReportsCsvView
                • org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView
                • org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
                • org.springframework.web.servlet.view.jasperreports.JasperReportsXlsView
              • org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView
            • org.springframework.web.servlet.view.document.AbstractPdfStamperView
            • org.springframework.web.servlet.view.AbstractTemplateView
              • org.springframework.web.servlet.view.freemarker.FreeMarkerView
              • org.springframework.web.servlet.view.velocity.VelocityView
                • org.springframework.web.servlet.view.velocity.VelocityToolboxView
                  • org.springframework.web.servlet.view.velocity.VelocityLayoutView
            • org.springframework.web.servlet.view.InternalResourceView
              • org.springframework.web.servlet.view.JstlView
              • org.springframework.web.servlet.view.tiles.TilesView
                • org.springframework.web.servlet.view.tiles.TilesJstlView
            • org.springframework.web.servlet.view.RedirectView
            • org.springframework.web.servlet.view.tiles2.TilesView
            • org.springframework.web.servlet.view.xslt.XsltView
          • org.springframework.web.servlet.view.xslt.AbstractXsltView
           
          和Controller一樣,View的第一個實現也是AbstractView。所以先讓我們看看AbstractView對render函數的實現:

           

          public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
          if (logger.isTraceEnabled()) {
          logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
          " and static attributes " + this.staticAttributes);
          }

          // Consolidate static and dynamic model attributes.
          Map mergedModel = new HashMap(this.staticAttributes.size() + (model != null ? model.size() : 0));
          mergedModel.putAll(this.staticAttributes);
          if (model != null) {
          mergedModel.putAll(model);
          }

          // Expose RequestContext?
          if (this.requestContextAttribute != null) {
          mergedModel.put(this.requestContextAttribute, createRequestContext(request, mergedModel));
          }

          prepareResponse(request, response);
          renderMergedOutputModel(mergedModel, request, response);
          }

          第一步,將靜態屬性和model的屬性都添加到mergedModel里面。如果需要請求上下文,則將請求上下文添加到model中。

          靜態屬性是繼承AbstractView進行設置的屬性。而請求上下文如果設置的名字就會創建一個request上下文。在requestContext中定義了一些包括本地化和主題的處理工具。

          第二步,對響應進行預處理。最后調用子類需要實現的函數renderMergedOutputModel。

          對PDF和EXCEL格式我們暫且不管,且Spring支持多種視圖技術,這里我們主要關注JSTL技術,

          接著我們來看AbstractUrlBasedView 類。在AbstractUrlBasedView 只定義了一個url屬性。別的沒有什么特殊處理。

          接著繼承AbstractUrlBasedView 的是InternalResourceView。他對renderMergedOutputModel進行實現,實現如下:

          /**
          * Render the internal resource given the specified model.
          * This includes setting the model as request attributes.
          */
          protected void renderMergedOutputModel(
          Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {

          // 獲取要暴露的request,一般都是傳入的參數request
          HttpServletRequest requestToExpose = getRequestToExpose(request);

          // 將model的數據添加到request屬性中
                  exposeModelAsRequestAttributes(model, requestToExpose);

          // 設置helper,如果存在的話
          exposeHelpers(requestToExpose);

          // 對繪制進行預處理,從而獲得到要分發的url
          String dispatcherPath = prepareForRendering(requestToExpose, response);

          // 獲取請求分發對象
          RequestDispatcher rd = requestToExpose.getRequestDispatcher(dispatcherPath);
          if (rd == null) {
          throw new ServletException(
          "Could not get RequestDispatcher for [" + getUrl() + "]: check that this file exists within your WAR");
          }

          // 決定使用RequestDispatcher的include方法還是forward方法
          if (useInclude(requestToExpose, response)) {
          response.setContentType(getContentType());
          if (logger.isDebugEnabled()) {
          logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
          }
          rd.include(requestToExpose, response);
          }

          else {
          // Note: The forwarded resource is supposed to determine the content type itself.
          exposeForwardRequestAttributes(requestToExpose);
          if (logger.isDebugEnabled()) {
          logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
          }
          rd.forward(requestToExpose, response);
          }
          }
          可以看到InternalResourceView對請求進行了轉發。轉發到url上。最后我們看看JSTLView的實現:

           
          public class JstlView extends InternalResourceView {
          
              private MessageSource messageSource;
          
              public JstlView() {
              }
          
              
              public JstlView(String url) {
                  super(url);
              }
          
              public JstlView(String url, MessageSource messageSource) {
                  this(url);
                  this.messageSource = messageSource;
              }
          
              protected void initServletContext(ServletContext servletContext) {
                  if (this.messageSource != null) {
                      this.messageSource = JstlUtils.getJstlAwareMessageSource(servletContext, this.messageSource);
                  }
                  super.initServletContext(servletContext);
              }
          
              protected void exposeHelpers(HttpServletRequest request) throws Exception {
                  if (this.messageSource != null) {
                      JstlUtils.exposeLocalizationContext(request, this.messageSource);
                  }
                  else {
                      JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
                  }
              }
          
          }

           

          在InternalResourceView  中,基本上所有的處理都差不多了。在JSTLView對兩個方法進行了覆蓋。第一個initServletContext,主要初始化了MessageResource

          第二個exposeHelpers將messageSource放在了request里面。

          這樣view的解析就結束了。接下來容器對jsp進行解析,并進行tag等的處理。然后將生成的頁面返回給客戶端。

          posted on 2009-11-26 13:25 追求無止境 閱讀(8209) 評論(2)  編輯  收藏

          評論

          # re: Spring MVC框架學習筆記 之 View技術  回復  更多評論   

          不錯。。。。
          2009-11-27 09:39 | 字典

          # re: Spring MVC框架學習筆記 之 View技術  回復  更多評論   

          99098
          2016-05-19 17:23 | 888

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 铜鼓县| 夏津县| 木兰县| 兴安盟| 嘉鱼县| 平安县| 南涧| 乌鲁木齐市| 宁波市| 鸡东县| 伽师县| 贞丰县| 嘉祥县| SHOW| 红原县| 齐齐哈尔市| 斗六市| 江陵县| 临洮县| 清水河县| 丘北县| 通化县| 东乡县| 儋州市| 松桃| 七台河市| 鹤峰县| 施秉县| 甘洛县| 理塘县| 临潭县| 洛川县| 天全县| 阳朔县| 三明市| 建昌县| 裕民县| 枣阳市| 张家口市| 夏河县| 于都县|