<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      JSP模板繼承功能實現

      背景

      最近剛入職新公司,瀏覽一下新公司項目,發現項目中大多數JSP頁面都是獨立的、完整的頁面,因此許多頁面都會有如下重復的代碼:

      <%@ page language="java" contentType="text/html; charset=UTF-8" import="java.util.Calendar"    pageEncoding="UTF-8"%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
      <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 
      <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
      <%@ taglib uri="/common-tags" prefix="m"%>
      <c:set var="ctx" value="${pageContext.request.contextPath}"></c:set>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
      <title>${webModule.module.name} ---xxxx</title>
      <meta name="keywords" content="xxxx"/>
      <meta name="description" content="xxxx"/>
      <link rel="stylesheet" href="${ctx}/css/web-bbs.css"/>
      <link rel="stylesheet" href="${ctx}/css/page.css"/>
      <script type="text/javascript" src="${ctx}/js/jquery-1.7.2.min.js"></script>
      <script type="text/javascript" src="${ctx}/js/bbs.js"></script>
      <script type="text/javascript" src="${ctx}/js/webUtil.js"></script>
      <script type="text/javascript" src="${ctx}/js/index.js"></script>
      <script type="text/javascript" src="${ctx}/js/faces.js"></script>

      小伙伴們每新添加一個頁面,就需要copy一份上面這坨代碼,還需要在各自頁面重復引入公共的頭尾文件(如header.jsp,footer.jsp等)。。。
      對于這種開發方式,重復的工作量就不多描述了,更重要的問題是這種架構方式未來會導致更多的維護工作量、甚至是bug隱患。
      舉兩個“栗子”:

      • 如果今后開發過程中我們需要全局引入、刪除一些公共的腳本(例如在線客服圖標、GA分析腳本等),變更一下jQuery的版本,更改DocType類型為Html5類型等等。要完成類似的需求我們必須逐個修改JSP文件,工作量就會與項目中JSP文件數量成正比。
      • 更麻煩的問題是,對于上述這些全局操作我們無法保證代碼是否是在所有頁面上都生效了,手工檢查?呵呵...

      解決方案

      上面扯了那么多,其實核心問題就是所有的jsp頁面都是各自為戰,沒有一個統一的公共的模板來維護一些全局的信息,所以這里就介紹一下我們以前的實現方案:

      1. 實現JSP文件的模板功能、讓所有的頁面都引入一個公共的模板。
      2. 公共部分信息直接在模板中維護,可變部分在模板中定義占位符,然后由頁面進行重寫來維護不同頁面的多樣性。

      有了模板以后就可以這樣寫頁面了:

            

      這樣的寫法好處顯而易見:

      • 首先,頁面結構一目了然,寫頁面時無須再關注內容以外的公共部分,減少了許多copy代碼的工作量,同時也降低出錯率
      • 其次,公共樣式、腳本等都在模板中引入,便于統一調整

      模板內容大概是這個樣子的:

            

      實現原理

      實現原理其實很簡單,模板功能的實現主要是兩個自定義標簽(自定義標簽的開發步驟這里就不講了)

      BlockTag

      該標簽主要用于在模板文件中定義相應的模塊(可以看做一個占位符),在渲染JSP頁面時會將標簽定義的位置替換為頁面重寫的內容,替換時根據標簽的name屬性加上特定的前綴作為key值從request的attribute中讀取內容。

      /**
       * 自定義標簽,用于在Jsp模板中占位
       * 
       * @author 逆風之羽
       *
       */
      public class BlockTag extends BodyTagSupport {
          /**
           * 占位模塊名稱
           */
          private String name;
      
          private static final long serialVersionUID = 1425068108614007667L;
          
          @Override
          public int doStartTag() throws JspException{
              return super.doStartTag();                
          }
          
          @Override
          public int doEndTag() throws JspException {
              ServletRequest request = pageContext.getRequest();
              //block標簽中的默認值
              String defaultContent = (getBodyContent() == null)?"":getBodyContent().getString();        
              String bodyContent = (String) request.getAttribute(OverwriteTag.PREFIX+ name);
              //如果頁面沒有重寫該模塊則顯示默認內容
              bodyContent = StringUtils.isEmpty(bodyContent)?defaultContent:bodyContent;
              try {
                  pageContext.getOut().write(bodyContent);
              } catch (IOException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }        
              // TODO Auto-generated method stub
              return super.doEndTag();
          } 
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
      }
      BlockTag代碼

      OverwriteTag

      該標簽主要用于在最終的頁面上重寫模板中的相應模塊,在頁面渲染時將標簽內部的內容寫入到當前request的attribute中,該標簽有一個必填參數name屬性作為該內容的key值,這個name屬性必須要和模板中對應要重寫的block的name值相同。

      /**
       * 自定義標簽,用于在jsp模板中重寫指定的占位內容
       * 
       * 基本原理:
       *         將overwrite標簽內容部分添加到ServletRequest的attribute屬性中
       *         在后續block標簽中再通過屬性名讀取出來,將其渲染到最終的頁面上即可
       * 
       * @author 逆風之羽
       *
       */
      public class OverwriteTag extends BodyTagSupport {
      
          private static final long serialVersionUID = 5901780136314677968L;
          //模塊名的前綴
          public static final String PREFIX = "JspTemplateBlockName_";
          //模塊名
          private String name;
          
          @Override
          public int doStartTag() throws JspException {
          
              // TODO Auto-generated method stub
              return super.doStartTag();
          }
          
          @Override
          public int doEndTag() throws JspException {
              ServletRequest request = pageContext.getRequest();
              //標簽內容
              BodyContent bodyContent = getBodyContent();
              request.setAttribute(PREFIX+name,  StringUtils.trim(bodyContent.getString()));        
              // TODO Auto-generated method stub
              return super.doEndTag();
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }    
      }
      OverwriteTag代碼

      總結與拓展

      1. 所有頁面都使用了模板以后,就可以很方便的控制項目全局的樣式、腳本,由于屏蔽了許多頁面公共信息,也使得日常頁面開發更加高效并減少錯誤率。
      2. JSP原生是不支持模板機制的,但是僅僅稍加一些手段使用兩個自定義標簽就可以實現模板功能,減少了許多重復的工作量。因此,工作過程中的痛點往往也是個人獲得成長的機會。
      3. 我在上面Demo中只簡單定義了一個base_template.jsp這一個模板,但是實際場景中一個網站可能有許多布局風格不同類型的頁面,那么一個模板顯然不能滿足多樣性的布局要求,這時我們就可以給模板進行分級將模板定義為base,common,channel三個級別,抽象程度從高到低,實現channel->common->base的繼承關系,不同風格的頁面只需要引入對應的channel模板即可,具體如何抽象還需根據實際的場景區別對待。
      posted @ 2015-06-24 09:54  逆風之羽  閱讀(3429)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 国产成人久久综合第一区| 国内不卡不区二区三区| 亚洲国产欧美一区二区好看电影| 国产精品欧美福利久久| 欧美人与动zozo在线播放| 一区二区和激情视频| 中文字幕久久人妻熟人妻| 成在线人永久免费视频播放| 四虎永久精品免费视频| 国产白嫩护士被弄高潮| 久久精品国产91精品亚洲| 精品乱码一区二区三四五区| 亚洲二区中文字幕在线| 国产又色又爽又黄的网站免费| 亚洲熟妇自偷自拍另欧美| 国产精品对白刺激久久久| 婷婷六月天在线| 国产精品熟妇视频国产偷人| 新晃| 一区天堂中文最新版在线| 四虎在线成人免费观看| 免费无码成人AV片在线 | 亚洲国产欧美在线人成| 色午夜一av男人的天堂| 日韩一区二区三在线观看| 国产成人精品中文字幕| 欧美另类图区清纯亚洲| 性xxxx搡xxxxx搡欧美| 性人久久久久| 国产精品亚洲五月天高清| 国产免费一区二区不卡| 无码日韩av一区二区三区| 亚洲av无码牛牛影视在线二区| 国产精品亚洲А∨天堂免下载| 部精品久久久久久久久| 亚洲va在线∨a天堂va欧美va| 亚洲黄色成人网在线观看| 久章草在线毛片视频播放| 国内揄拍国内精品人妻| 高清中文字幕国产精品| 亚洲成熟女人毛毛耸耸多|