整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          如何應用Web頁面靜態化技術以提高Web應用系統的響應性能

          件項目實訓及課程設計指導——如何應用Web頁面靜態化技術提高Web應用系統的響應性能

          1、什么是Web頁面靜態化技術

          (1)Web頁面靜態化技術

          將JSP動態頁面按照某種模板格式生成對應的*.html純靜態Web頁面的過程,稱之為Web頁面靜態化技術。

          (2)何種場合需要應用Web頁面靜態化技術

          當有些企業應用系統中的頁面信息在一段時間內不發生變化時(比如內容管理系統、網上商城中的商品信息等),可以應用Web頁面靜態化技術,這樣可以提高整個系統的響應效率——因為無須再訪問后臺數據庫系統、也不需要再次編譯處理JSP動態頁面文件,因此能夠減少對Web應用系統的消耗和性能影響。

          2、為什么要應用Web頁面靜態化技術

          目前基于B/S(Browser/Server,瀏覽器/服務器模式)體系架構的企業應用系統基本上都是由動態Web頁面所構成的(比如由*.jsp、*.aspx、*.php等類型),正因為是動態化的Web頁面才能滿足不同的Web瀏覽者的個性化的訪問需要、并且能夠與訪問者產生相互交互。

          但為了能夠產生出動態的應用效果,用戶每一次對目標頁面的HTTP請求都會在Web服務器端對這些動態Web頁面進行編譯或者動態處理,而這些操作都是很消耗Web服務器系統資源的。

          如果目標頁面文件(比如*.jsp)在一定的時間內,其動態顯示的內容不會發生改變(比如新聞系統中的新聞信息顯示、網點中的商品分類和某一商品信息的詳情頁等),那么就沒有必要為每一次對它的HTTP請求訪問,都進行一次"新"的編譯或執行。此時可以在用戶第一次對它訪問后,就把它在這段沒有發生改變的時間內的頁面處理結果保存到一個純靜態的頁面文件(*.html格式)或者有靜態效果的其它格式頁面文件(*.vm、*.ftl等形式)中,然后用戶以后每次再訪問這個動態Web頁面時,后臺Web服務器系統程序就直接采用轉換后的靜態頁面內容進行響應。

          因此,經過靜態化技術轉換處理后的結果Web頁面能夠快速地響應用戶的HTTP請求,而且還能夠大大地減少對Web服務器系統資源的消耗。當然,為了能夠達到靜態化的功能實現目標,軟件應用系統的開發人員可以在Web應用系統的開發中應用各種模板技術——比如Velocity模板、FreeMarker模板技術等。當然,讀者如果熟悉Web頁面靜態化技術的實現原理后,也可以自己編程實現。

          在Web應用系統的表示層開發中如何通過應用Velocity模板技術以提高Web應用系統的響應性能,作者在以前的文章中的做了詳細的介紹,有興趣的讀者可以翻看文章《軟件項目實訓及課程設計指導——如何在Web應用系統表示層開發實現中應用Velocity模板技術》。

          作者在下文將為讀者介紹如何在Web應用系統的表示層開發中應用FreeMarker模板技術以提高Web應用系統的響應性能。

          3、在Web應用系統的表示層開發中應用FreeMarker模板技術

          (1)FreeMarker模板是什么、怎么理解"模板引擎"的概念

          FreeMarker 和Velocity都屬于"模板引擎"(作者注:"模板引擎"在J2EE平臺中一般為框架形式的系統程序和相關的系統庫),開發人員應用這些模板引擎所提供的模板語言處理相關的數據,模板引擎系統會按照開發人員的要求輸出文本,這些文本的格式可以是HTML網頁、電子郵件、配置文件以及源代碼等形式。

          如下代碼示例為在標準的HTML頁面中內嵌FreeMarker模板語言的語句(參看其中的黑體標識的語句)的示例。

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html> <head> <title>showInfoTemplate.ftl</title>
          <meta http-equiv="content-type" content="text/html; charset=gb2312">
          </head> <body>
              <h2>采用標準的方式獲得參數值: ${showResultInfo}</h2 > <br>
              <h2>采用FreeMarker模板的內建變量的方式獲得參數值: ${Request.showResultInfo }</h2 > <br>
          </body></html>

          (2)為什么要應用FreeMarker等類型的模板技術

          談到"模板"的概念,相信讀者應該不會感覺到陌生感,在生活中大量地應用各種各樣的"模板",應用的目的讀者也應該都會理解。同樣,在計算機軟件應用系統中也大量地提高各種模板和應用各種模板來簡化和加速某項"工作",比如Word中的文檔格式模板、編程語言中的print("%各種格式符")語句中的替換模板等等。而在J2EE系統平臺的應用系統開發中之所以應用FreeMarker模板技術:

          首先,FreeMarker模板技術同樣也能夠實現Web應用系統中的表示邏輯和數據處理邏輯相互分離——這是通過在模板文件中包裝HTML標簽實現的。

          FreeMarker模板采用標準的Web Servlet程序中所提供的模型數據動態地生成目標HTML頁面文件。在Web應用系統開發中如果應用FreeMarker模板技術,界面開發人員只需要關注于界面(也就是FreeMarker的模板文件)的開發,而系統中的業務邏輯的開發人員也只需要負責將需要顯示的數據填入到FreeMarker的模板文件的數據模型中。最終由FreeMarker模板引擎負責合并數據模型和模板文件,然后產生出完整的Web頁面文件并輸出到Web瀏覽器中。

          其次,實現將基于動態化技術的各種Web頁面(如*.jsp、*.aspx、*.php等)轉換為靜態的HTML格式或其它文本格式的Web頁面,達到"動態頁面靜態化"的高效響應的應用效果。

          因此,模板引擎不只是可以讓開發人員實現代碼級別的分離(如系統中的業務邏輯代碼和用戶界面展示控制代碼的分離),也可以實現軟件應用系統中的數據分離(如動態可變數據與靜態固定數據相互分離),甚至還可以實現應用系統中的代碼單元共享(代碼重用)等效果。

          4、Struts及Struts2應用框架都全面地支持FreeMarker模板技術

          (1)FreeMarker模板特別適應于基于MVC體系架構模式的Web應用系統

          Struts2應用框架默認采用FreeMarker作為其模板文件,并且Struts2應用框架中所有的主題模板文件都是采用FreeMarker模板技術編寫的。

          (2)Struts2應用框架全面提供對FreeMarker模板技術的支持

          在基于Struts2應用框架的Web應用系統中,開發人員只需要將項目中的Action類的配置定義中的結果<result>標簽中的type屬行設置為:type="freemarker",就可以自動地由Struts2應用框架中內帶的FreeMarker引擎完成模型數據和模板文件的總裝配和輸出(參看如下示例圖所示)。

          (3)Struts應用框架也同樣提供對FreeMarker模板技術的支持

          而在Struts應用框架中應用FreeMarker模板技術,開發人員只需要在Web應用系統的部署描述文件web.xml中配置出與FreeMarker模板相關的FreemarkerServlet組件(參看如下示例圖所示),然后由該FreemarkerServlet組件將項目中的相關Action類中所保存的模型數據和模板文件相互集成組裝成最終的HTML頁面文件、并向Web瀏覽器輸出。

          作者將在下文及后續文章中為讀者介紹在J2EE Web應用系統、J2EE Struts應用框架的應用系統及J2EE Struts2應用框架的應用系統等環境中如何應用FreeMarker模板技術實現Web頁面靜態化的應用效果。作者首先在下文為讀者介紹在J2EE Web應用系統環境中如何應用FreeMarker模板技術。

          5、在J2EE Web應用項目中添加一個JSP頁面文件

          (1)在Web項目的userManage目錄下添加一個文件名稱為fmtWebUserLogin.jsp的JSP頁面文件,該頁面主要功能是模擬用戶系統登錄,其中包含有一個標準的HTML表單,創建的過程參看如下示例圖所示。

          (2)fmtWebUserLogin.jsp頁面文件的代碼示例

          <%@ page language="java" pageEncoding="GB18030"%>
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html><head><title>My JSP 'fmtUserLogin.jsp' starting page</title>
          </head><body>
              <form action="/Struts2Web/fmtServletAction" method="post" >
                  您的名稱:<input type="text" name="userName" /> <br />
                  您的密碼:<input type="password" name="userPassWord" /> <br />
                  <input type="submit" value="提交" name="submitButton" onclick="this.value='正在提交請求,請稍候'"/>
                  <input type="reset" value="取消" />
              </form>
          </body></html>

          (3)fmtWebUserLogin.jsp頁面靜態預覽的效果圖如下圖所示

          6、在J2EE Web應用項目中添加一個Servlet組件

          在J2EE Web應用系統中使用FreeMarker模板時,應該讓J2EE Servlet組件來合并模板和數據。因此J2EE Servlet組件負責創建Configuration類型的對象實例,并負責合并模板和數據。

          (1)程序包名稱為com.px1987.struts2.servlet,類名稱為FMTServletAction,創建的過程參看如下示例圖所示。

          (2)將J2EE Servlet組件的URL-Pattern設置為/fmtServletAction,創建的過程參看如下示例圖所示。

          (3)FMTServletAction程序類的代碼示例

          package com.px1987.struts2.servlet;
          import java.io.IOException;
          import java.io.Writer;
          import java.util.HashMap;
          import java.util.Map;
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import freemarker.template.Configuration;
          import freemarker.template.Template;
          import freemarker.template.TemplateException;
          public class FMTServletAction extends HttpServlet {
                private Configuration oneConfiguration=null;
                public FMTServletAction() {
                			super();
                }
                public void init() throws ServletException {
                      /** 初始化FreeMarker配置,并創建出一個Configuration的實例 */
                      oneConfiguration = new Configuration(); //設置FreeMarker的模版文件位置
                      oneConfiguration.setServletContextForTemplateLoading(getServletContext(),"userManage");
                      } //第一個參數是本web應用的 ServletContext,第二個參數是模板文件的路徑
                      public void destroy() {
                      super.destroy();
                }
                public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
                      String resultMessage=null;
                      String userName=request.getParameter("userName");
                      String userPassWord=request.getParameter("userPassWord");
                      boolean returnResult=userName.equals("yang") &&userPassWord.equals("1234");
                      if(returnResult){
                      			resultMessage =userName+"您登錄成功!";
                      }
                      else{
                      			resultMessage =userName+"您的身份信息無效!";
                      }
                      Map oneHashMap = new HashMap();
                      oneHashMap.put("showResultInfo", resultMessage); //取得模版文件
                      Template oneTemplate= oneConfiguration.getTemplate("showInfoFMTTemplate.ftl");
                      response.setContentType("text/html; charset=gb2312");
                      Writer out = response.getWriter();
                      try{ //結果必須輸出到HttpServletResponse中,才能被瀏覽器加載
                      			oneTemplate.process(oneHashMap, out);
                      }
                      catch (TemplateException e){
                      			throw new ServletException("加載FreeMarker的模板文件時出現了錯誤", e);
                      }
                }
          }

          7、在J2EE Web應用項目中添加一個FreeMarker模板文件

          (1)模板文件的名稱為showInfoFMTTemplate.ftl,創建的過程參看如下示例圖所示。

          (2)模板文件showInfoFMTTemplate.ftl的代碼示例如下,注意其中黑體標識的代碼

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html> <head> <title>showInfoTemplate.ftl</title>
          <meta http-equiv="content-type" content="text/html; charset=gb2312">
          </head> <body>
          			<h2>采用標準的方式獲得參數值: ${showResultInfo}</h2 > <br>
          </body></html>

          8、部署本Web項目并啟動測試頁面以驗證本示例的功能

          (1)正確地部署完畢本Web項目后,在瀏覽器的URL地址欄中輸入如下示圖中的訪問地址,啟動測試頁面 ,執行的結果參看如下示例圖所示。

          (2)在測試頁面的表單中模擬用戶登錄系統的狀態,輸入相關的登錄參數后的執行結果參看如下示例圖所示。

          從本示例的執行結果來看,在showInfoFMTTemplate.ftl頁面中同樣也可以獲得在傳統的J2EE Web應用環境中一般由動態JSP類型的Web頁面才能獲得的動態結果數據,但本示例中的*.ftl頁面是靜態效果的Web頁面。因此,最終實現和達到了"動態頁面靜態化"的高效響應的應用效果。

          作者為了能夠讓讀者進一步地理解"動態頁面靜態化"的應用效果,可以通過瀏覽結果頁面相關的源程序從而確認最終是否為一個HTML格式的純靜態頁面。讀者可以在Web瀏覽器中右鍵單擊,然后在彈出的快捷菜單項目中選擇"查看源文件"的功能子菜單項目(參看如下示例圖所示)。

          將在Web瀏覽器中顯示出用戶當前正在瀏覽的Web頁面的源代碼,熟悉HTML語言的讀者應該能夠看懂其中的代碼含義——全部為HTML格式的純靜態頁面標簽。

          如何應用XML+XSLT+AJAX組合技術實現無刷新數據查詢

          應用XML+XSLT技術分離Web應用表示層數據和樣式的實例

          如何應用“XML+XSLT”技術分離Web表示層數據和樣式

          課程設計指導——應用AJAX技術提高Web應用的整體響應性能

          如何在Web應用系統表示層開發中應用Velocity模板技術


          WEB系列】靜態資源配置與讀取

          SpringWeb項目除了我們常見的返回json串之外,還可以直接返回靜態資源(當然在現如今前后端分離比較普遍的情況下,不太常見了),一些簡單的web項目中,前后端可能就一個人包圓了,前端頁面,js/css文件也都直接放在Spring項目中,那么你知道這些靜態資源文件放哪里么

          I. 默認配置

          1. 配置

          靜態資源路徑,SpringBoot默認從屬性spring.resources.static-locations中獲取

          默認值可以從org.springframework.boot.autoconfigure.web.ResourceProperties#CLASSPATH_RESOURCE_LOCATIONS獲取

          private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
          			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
          
          /**
           * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
           * /resources/, /static/, /public/].
           */
          private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
          復制代碼

          注意上面的默認值,默認有四個,優先級從高到低

          • /META-INF/resources/
          • /resources/
          • /static/
          • /public/

          2. 實例演示

          默認靜態資源路徑有四個,所以我們設計case需要依次訪問這四個路徑中的靜態資源,看是否正常訪問到;其次就是需要判定優先級的問題,是否和上面說的一致

          首先創建一個SpringBoot web項目,工程創建流程不額外多說,pom中主要確保有下面依賴即可(本文使用版本為: 2.2.1.RELEASE)

          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          復制代碼

          在資源文件夾resources下,新建四個目錄,并添加html文件,用于測試是否可以訪問到對應的資源文件(主要關注下圖中標紅的幾個文件)



          a. META-INF/resources

          靜態文件 m.html

          <html>
          <title>META-INF/resource/m.html</title>
          <body>
          jar包內,META-INF/resources目錄下 m.html
          </body>
          </html>
          復制代碼

          完成對應的Rest接口

          @GetMapping(path = "m")
          public String m() {
              return "m.html";
          }
          復制代碼



          b. resources

          靜態文件 r.html

          <html>
          <title>resources/r.html</title>
          <body>
          jar包內,resouces目錄下 r.html
          </body>
          </html>
          復制代碼

          對應的Rest接口

          @GetMapping(path = "r")
          public String r() {
              return "r.html";
          }
          復制代碼



          c. static

          靜態文件 s.html

          <html>
          <title>static/s.html</title>
          <body>
          jar包內,static目錄下 s.html
          </body>
          </html>
          復制代碼

          對應的Rest接口

          @GetMapping(path = "s")
          public String s() {
              return "s.html";
          }
          復制代碼



          d. public

          靜態文件 p.html

          <html>
          <title>public/p.html</title>
          <body>
          jar包內,public目錄下 p.html
          </body>
          </html>
          復制代碼

          對應的Rest接口

          @GetMapping(path = "p")
          public String p() {
              return "p.html";
          }
          復制代碼



          e. 優先級測試

          關于優先級的測試用例,主要思路就是在上面四個不同的文件夾下面放相同文件名的靜態資源,然后根據訪問時具體的返回來確定相應的優先級。相關代碼可以在文末的源碼中獲取,這里就不贅述了

          II. 自定義資源路徑

          一般來講,我們的靜態資源放在上面的四個默認文件夾下面已經足夠,但總會有特殊情況,如果資源文件放在其他的目錄下,應該怎么辦?

          1. 修改配置文件

          第一種方式比較簡單和實用,修改上面的spring.resources.static-locations配置,添加上自定義的資源目錄,如在 application.yml 中,指定配置

          spring:
            resources:
              static-locations: classpath:/out/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
          復制代碼

          上面指定了可以掃描/out目錄下的靜態資源文件,且它的優先級是最高的(上面的配置順序中,優先級的高低從左到右)

          實例演示

          在資源目錄下,新建文件/out/index.html



          請注意在其他的四個資源目錄下,也都存在 index.html這個文件(根據上面優先級的描述,返回的應該是/out/index.html)

          @GetMapping(path = "index")
          public String index() {
              return "index.html";
          }
          復制代碼



          2. WebMvcConfigurer 添加資源映射

          除了上述的配置指定之外,還有一種常見的使用姿勢就是利用配置類WebMvcConfigurer來手動添加資源映射關系,為了簡單起見,我們直接讓啟動類實現WebMvcConfigure接口

          @SpringBootApplication
          public class Application implements WebMvcConfigurer {
              @Override
              public void addResourceHandlers(ResourceHandlerRegistry registry) {
                  // 請注意下面這個映射,將資源路徑 /ts 下的資源,映射到根目錄為 /ts的訪問路徑下
                  // 如 ts下的ts.html, 對應的訪問路徑 /ts/ts
                  registry.addResourceHandler("/ts/**").addResourceLocations("classpath:/ts/");
              }
          
          
              public static void main(String[] args) {
                  SpringApplication.run(Application.class);
              }
          }
          復制代碼

          根據上面的配置表示將/ts目錄下的資源ts.html,映射到/ts/ts,而直接訪問/ts會報404(這個邏輯可能有點繞,需要仔細想一想)

          @GetMapping(path = "ts")
          public String ts() {
              return "ts.html";
          }
          
          @GetMapping(path = "ts/ts")
          public String ts2() {
              return "ts.html";
          }
          復制代碼



          III. Jar包資源訪問

          前面描述的靜態資源訪問主要都是當前包內的資源訪問,如果我們的靜態資源是由第三方的jar包提供(比如大名鼎鼎的Swagger UI),這種時候使用姿勢是否有不一樣的呢?

          1. classpath 與 classpath*

          在之前使用SpringMVC3+/4的時候,classpath:/META-INF/resources/表示只掃描當前包內的/META-INF/resources/路徑,而classpath*:/META-INF/resources/則會掃描當前+第三方jar包中的/META-INF/resources/路徑

          那么在SpringBoot2.2.1-RELEASE版本中是否也需要這樣做呢?(答案是不需要,且看后面的實例)

          2. 實例

          新建一個工程,只提供基本的html靜態資源,項目基本結構如下(具體的html內容就不粘貼了,墻裂建議有興趣的小伙伴直接看源碼,閱讀效果更優雅)



          接著在我們上面常見的工程中,添加依賴

          <dependency>
              <groupId>com.git.hui.boot</groupId>
              <artifactId>204-web-static-resources-ui</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </dependency>
          復制代碼

          添加對應資源的訪問端點

          @GetMapping(path = "ui")
          public String ui() {
              return "ui.html";
          }
          
          @GetMapping(path = "out")
          public String out() {
              return "out.html";
          }
          
          // 第三方jar包的 META-INF/resources 優先級也高于當前包的 /static
          
          @GetMapping(path = "s2")
          public String s2() {
              return "s2.html";
          }
          復制代碼

          請注意,這個時候我們是沒有修改前面的spring.resources.static-locations配置的



          上面的訪問結果,除了說明訪問第三方jar包中的靜態資源與當前包的靜態資源配置沒有什么區別之外,還可以得出一點

          • 相同資源路徑下,當前包的資源優先級高于jar包中的靜態資源
          • 默認配置下,第三方jar包中META-INF/resources下的靜態資源,優先級高于當前包的/resources, /static, /public

          IV. 其他

          0. 項目

          • 工程:github.com/liuyueyi/sp…
          • 源碼:github.com/liuyueyi/sp…
          • github.com/liuyueyi/sp…

          1. 一灰灰Blog

          盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

          學習記錄的代碼,部分參考自gitee碼云的如下兩個工程。這兩個個工程有詳盡的Spingboot1.x和2.x教程。鳴謝!

          https://gitee.com/didispace/SpringBoot-Learning.git

          https://gitee.com/jeff1993/springboot-learning-example.git

          本學習記錄的示例代碼克隆地址,分支為develop

          https://gitee.com/kutilion/MyArtifactForEffectiveJava.git

          靜態資源

          通常實際的項目中會引入大量的靜態資源。比如圖片,樣式表css,腳本js,靜態html頁面等。這章主要學習引入模板來實現訪問靜態資源。

          一般Springboot提供的默認靜態資源存放位置是/resources之下。html的文件一般存放在/resources/templates中。

          渲染靜態頁面通常會用到模板。模板種類很多,這里介紹兩種:

          • Thymeleaf
          • FreeMarker

          另外比較常用的模板還有velocity,但是velocity在Springboot1.5開始就不被支持了。

          示例相關代碼如下:

          Thymeleaf

          • studySpringboot.n06.webframework.web.WebController.java
          • templates/06_webframework/thymeleaf.html

          FreeMarker

          • studySpringboot.n06.webframework.web.WebController.java
          • templates/06_webframework/freemarker.ftl

          Thymeleaf

          build.gradle

          為了使用Thymeleaf模板,需要在build.gradle腳本中引入模板引擎的依賴

          implementation 'org.springframework.boot:spring-boot-starter-thymeleaf
          

          WebController.java

          控制器類中聲明訪問路徑,并且為模板添加一個變量

           @RequestMapping("/thymeleaf")
           public String ThymeleafTest(ModelMap map) {
           map.addAttribute("host", "http://blog.kutilionThymeleaf.com");
           return "06_webframework/thymeleaf"; 
           }
          

          注意這個方法的返回值,因為靜態頁面沒有直接放在templates文件夾下,而是放在templates文件夾的子文件夾06_webframework中,所以返回值中要把路徑帶上

          thymeleaf.html

          靜態頁面中使用了el表達式,可以將java變量反映到頁面上

          <!DOCTYPE html>
          <html>
          <head lang="en">
           <meta charset="UTF-8" />
           <title></title>
          </head>
          <body>
          <h1 th:text="${host}">This Thymeleaf framework test page.</h1>
          </body>
          </html>
          

          執行結果:

          FreeMarker

          原理和Thymeleaf基本是一樣的

          build.gradle

          implementation 'org.springframework.boot:spring-boot-starter-freemarker'
          

          WebController.java

           @RequestMapping("/freemarker")
           public String FreeMarkerTest(ModelMap map) {
           map.addAttribute("host", "http://blog.kutilionFreemarker.com");
           return "06_webframework/thymeleaf";
           }
          

          freemarker.ftl

          <!DOCTYPE html>
          <html>
          <head lang="en">
           <meta charset="UTF-8" />
           <title></title>
          </head>
          <body>
          <h1 th:text="${host}">This Freemarker framework test page.</h1>
          </body>
          </html>
          

          執行結果:

          總結

          • 引入并且使用了Thymeleaf和FreeMarker模板
          • Springboot默認已經配置好這兩種模板了,如果需要手動配置需要參考兩種模板的文檔

          主站蜘蛛池模板: 无码人妻精品一区二区三| 一区二区不卡久久精品| 国产在线观看精品一区二区三区91 | 日韩中文字幕一区| www一区二区三区| 天天视频一区二区三区| 69福利视频一区二区| 精品一区二区三区中文字幕| 久久精品国产一区二区 | 国产精品va无码一区二区| 国产伦精品一区二区三区在线观看 | 欧洲精品一区二区三区| 中文字幕一区二区三匹| 男女久久久国产一区二区三区| 大伊香蕉精品一区视频在线 | 大香伊人久久精品一区二区| 一区二区三区精品| 日韩精品在线一区二区| 久久精品国产一区| 精品一区二区三区中文字幕| 一区二区视频传媒有限公司| 国模无码人体一区二区| 波多野结衣免费一区视频| 国产福利电影一区二区三区| 国产精品一区二区三区99| 日韩电影在线观看第一区| 色多多免费视频观看区一区| 蜜桃视频一区二区| 538国产精品一区二区在线| 肥臀熟女一区二区三区| 熟妇人妻系列av无码一区二区| 精品国产福利第一区二区三区| 无码精品视频一区二区三区| 精品欧洲av无码一区二区14| 无码一区二区三区AV免费| 国产伦精品一区二区三区精品| 无码人妻久久一区二区三区蜜桃 | 国产成人精品视频一区二区不卡| 日本精品一区二区三区在线观看| 久久综合亚洲色一区二区三区 | 精品一区精品二区|