JSP生成靜態HTML頁面的幾種方法

一、從數據庫中取相應數據並替換掉模板中的對應標籤,下面是一個簡單的示例

1.buildhtml.jsp

<%@ page contentType="text/html; charset=gb2312" import="java.util.*,java.io.*"%>

<%

try{

String title="This is Title";

String content="This is Content Area";

String editer="LaoMao";

String filePath = "";

filePath = request.getRealPath("/")+"test/template.htm";

//out.print(filePath+"<br>");

String templateContent="";

FileInputStream fileinputstream = new FileInputStream(filePath);//讀取模塊文件

int lenght = fileinputstream.available();

byte bytes[] = new byte[lenght];

fileinputstream.read(bytes);

fileinputstream.close();

templateContent = new String(bytes);

//out.print(templateContent);

templateContent=templateContent.replaceAll("###title###",title);

templateContent=templateContent.replaceAll("###content###",content);

templateContent=templateContent.replaceAll("###author###",editer);//替換掉模塊中相應的地方

//out.print(templateContent);

// 根據時間得文件名

Calendar calendar = Calendar.getInstance();

String fileame = String.valueOf(calendar.getTimeInMillis()) +".html";

fileame = request.getRealPath("/")+fileame;//生成的html文件保存路徑

FileOutputStream fileoutputstream = new FileOutputStream(fileame);//建立文件輸出流

byte tag_bytes[] = templateContent.getBytes();

fileoutputstream.write(tag_bytes);

fileoutputstream.close();

}

catch(Exception e){

out.print(e.toString());

}

%>

2. template.htm

<html>

<head>

<title>###title###</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<LINK href="../css.css" rel=stylesheet type=text/css>

</head>

<body>

<table width="500" border="0" align="center" cellpadding="0" cellspacing="2">

   <tr> 

     <td align="center">###title###</td>

   </tr>

   <tr> 

     <td align="center">author:###author###&nbsp;&nbsp;</td>

   </tr>

   <tr>

     <td>###content###</td>

   </tr>

</table>

</body>

</html>

=======================================================

二、從動態頁的URL獲取相應頁面內容並寫入到文件

/*

* Created on 2006-3-4

* To change the template for this generated file go to

* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/

package com.easydone.cn.tools.utils;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.Date;

/**

* @author Administrator

* To change the template for this generated type comment go to

* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/

public class MakeHtml {

         private static long star = 0;

         private static long end = 0;

         private static long ttime = 0;

         //返回html代碼

         public static String getHtmlCode(String httpUrl){

         Date before = new Date();

         star = before.getTime();

         String htmlCode = "";

         try {

         InputStream   in;

         URL url = new java.net.URL(httpUrl);

         HttpURLConnection connection = (HttpURLConnection)url.openConnection();

         connection = (HttpURLConnection) url.openConnection();

         connection.setRequestProperty("User-Agent","Mozilla/4.0");

         connection.connect();

         in = connection.getInputStream();

         java.io.BufferedReader breader = new BufferedReader(new InputStreamReader(in , "GBK"));

         String currentLine;

           while((currentLine=breader.readLine())!=null){

         htmlCode+=currentLine;

           }

         } catch (Exception e) {

         e.printStackTrace();

         }finally{

         Date after = new Date();

         end = after.getTime();

         ttime = end-star ;

         System.out.println("執行時間:"+ttime +"秒");

         }

         return htmlCode;

         }

         //存儲文件

         public static synchronized void writeHtml(String filePath,String info,String flag) {

         PrintWriter pw = null;

         try {

         File writeFile = new File(filePath);

         boolean isExit = writeFile.exists();

         if (isExit != true) {

         writeFile.createNewFile();

         } else {

         if (!flag.equals("NO")) {

         writeFile.delete();

         writeFile.createNewFile();

         } 

         }

         pw = new PrintWriter(new FileOutputStream(filePath, true));

         pw.println(info);

         pw.close();

         } catch (Exception ex) {

         System.out.println(ex.getMessage());

         }finally{

         pw.close();

         }

         }

         public static void main(String[] args) {

         String url = "http://www.easydone.cn/index.htm";

         writeHtml("c:/demo.htm",getHtmlCode(url),"NO");

         }

}

三、利用Filter和定製Response,把服務器返回的JSP響應輸出到我們自己的Response中,就可以將響應快速寫入Html文件,然後再發送給客戶。

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.util.Calendar;

public class CacheFilter implements Filter {

   ServletContext sc;

   FilterConfig fc;

   long cacheTimeout = Long.MAX_VALUE;

   public void doFilter(ServletRequest req,

                        ServletResponse res,

                        FilterChain chain)

       throws IOException, ServletException {

     HttpServletRequest request =

         (HttpServletRequest) req;

     HttpServletResponse response =

         (HttpServletResponse) res;

     // check if was a resource that shouldn't be cached.

     String r = sc.getRealPath("");

     String path = 

         fc.getInitParameter(request.getRequestURI());

     if (path!= null && path.equals("nocache")) {

       chain.doFilter(request, response);

       return;

     }

     path = r+path;

     String id = request.getRequestURI() + 

         request.getQueryString();

     File tempDir = (File)sc.getAttribute(

       "javax.servlet.context.tempdir");

     // get possible cache

     String temp = tempDir.getAbsolutePath();

     File file = new File(temp+id);

     // get current resource

     if (path == null) {

       path = sc.getRealPath(request.getRequestURI());

     }

     File current = new File(path);

     try {

       long now =

         Calendar.getInstance().getTimeInMillis();

       //set timestamp check

       if (!file.exists() || (file.exists() &&

           current.lastModified() > file.lastModified()) ||

           cacheTimeout < now - file.lastModified()) {

         String name = file.getAbsolutePath();

         name =

             name.substring(0,name.lastIndexOf("/"));

         new File(name).mkdirs();

         ByteArrayOutputStream baos =

             new ByteArrayOutputStream();

         CacheResponseWrapper wrappedResponse =

           new CacheResponseWrapper(response, baos);

         chain.doFilter(req, wrappedResponse);

         FileOutputStream fos = new FileOutputStream(file);

         fos.write(baos.toByteArray());

         fos.flush();

         fos.close();

       }

     } catch (ServletException e) {

       if (!file.exists()) {

         throw new ServletException(e);

       }

     }

     catch (IOException e) {

       if (!file.exists()) {

         throw e;

       }

     }

     FileInputStream fis = new FileInputStream(file);

     String mt = sc.getMimeType(request.getRequestURI());

     response.setContentType(mt);

     ServletOutputStream sos = res.getOutputStream();

     for (int i = fis.read(); i!= -1; i = fis.read()) {

       sos.write((byte)i);

     }

   }

   public void init(FilterConfig filterConfig) {

     this.fc = filterConfig;

     String ct =

         fc.getInitParameter("cacheTimeout");

     if (ct != null) {

       cacheTimeout = 60*1000*Long.parseLong(ct);

     }

     this.sc = filterConfig.getServletContext();

   }

   public void destroy() {

     this.sc = null;

     this.fc = null;

   }

}

參考文章:

使用Filter實現靜態HTML緩衝(一種折中方法) 

緩衝是Web應用中必須考慮的一個提高性能的重要手段。對於基於JSP/Servlet技術的站點,常用的緩衝有持久層的數據庫連接池緩衝,內存中的值對象緩衝,JSP頁面緩衝,以及各種各樣的緩衝框架等等,無不是爲了提高系統的吞吐量。

然而對於大型站點來說,將JSP頁面轉換爲靜態Html也許是最高效的方法,特別適合於數據不經常變化但是頁面訪問量特別大的站點,如新聞等,通過把JSP動態頁面預先轉換爲靜態Html頁面,當用戶請求此頁面時,系統自動導向到對應的Html頁面,從而避免解析JSP請求,調用後臺邏輯以及訪問數據庫等操作所帶來的巨大開銷。

如何將一個已有的JSP站點的動態JSP頁面轉化爲靜態Html呢?我們希望在不用更改現有Servlet,JSP的前提下讓系統自動將這些JSP轉換爲Html頁。幸運的是,Filter爲我們提供了一種實現方案。

Filter是Servlet 2.2規範中最激動人心的特性。Filter能過濾特定URL如/admin/*並進行必要的預處理,如修改Request和Response,從而實現定製的輸入輸出。更強大的是,Filter本身是一個責任鏈模式,它能一個接一個地傳遞下去,從而將實現不同功能的Filter串起來,並且可以動態組合。

要自動生成靜態頁面,用Filter截獲jsp請求並先進行預處理,自動生成Html,是個不錯的主意。一個很容易想到的方法是在Filter截獲Request後,導向一個Servlet,在這個Servlet中向本機發送一個http請求,然後將響應寫入一個文件:

   URLConnection urlConn = URLConnection.open(http://localhost/req); 

注意要避免遞歸。

另一個方法是不模擬http,而是定製Response,把服務器返回的JSP響應輸出到我們自己的Response中,就可以將響應快速寫入Html文件,然後再發送給客戶。而且,由於沒有http模擬請求,直接讀取服務器響應速度非常快。

截獲Response的關鍵便是實現一個WrappedResponse,讓服務器將響應寫入我們的WrappedResponse中。這類似於一個代理模式,Servlet 2.x已經提供了一個WrappedResponse類,我們只需要複寫其中的一些關鍵方法即可。

WrappedResponse實現了Response接口,它需要一個Response作爲構造函數的參數,事實上這正是代理模式的應用:WrappedResponse充當了代理角色,它會將JSP/Servlet容器的某些方法調用進行預處理,我們需要實現自己的方法。

綜上:用Filter實現HTML緩衝的步驟是:

1. 用Filter截獲請求,如/a.jsp?id=123,映射到對應的html文件名爲/html/a.jsp$id=123.htm。

2. 查找是否有/html/a.jsp$id=123.htm,如果有,直接forward到此html,結束。

3. 如果沒有,實現一個WrappedResponse,然後調用filterChain(request, wrappedResponse)。

4. 將返回的WrappedResponse寫入文件/html/a.jsp$id=123.htm,然後返回響應給用戶。

5. 下一次用戶發送相同的請求時,到第2步就結束了。 

使用這個方法的好處是不用更改現有的Servlet,JSP頁,限制是,JSP頁面結果不能與Session相關,需要登陸或用戶定製的頁面不能用這種方法緩衝。
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章