1. 通過(guò)freemarker靜態(tài)化
2. 通過(guò)jsp filter靜態(tài)化
主要思路:請(qǐng)求servlet->判斷靜態(tài)文件是否存在并且靜態(tài)文件創(chuàng)建時(shí)間是否在閥值之內(nèi)-->如果不是,則訪問(wèn)數(shù)據(jù)庫(kù)生成靜態(tài)文件->否則直接跳轉(zhuǎn)靜態(tài)文件
然后通過(guò)urlReWrite直接將訪問(wèn)servlet的請(qǐng)求改為html,完成seo
最后通過(guò)SQUID緩存前臺(tái)數(shù)據(jù)
一、從數(shù)據(jù)庫(kù)中取相應(yīng)數(shù)據(jù)并替換掉模板中的對(duì)應(yīng)標(biāo)簽,下面是一個(gè)簡(jiǎn)單的示例
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);//替換掉模塊中相應(yīng)的地方
//out.print(templateContent);
// 根據(jù)時(shí)間得文件名
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### </td>
</tr>
<tr>
<td>###content###</td>
</tr>
</table>
</body>
</html>
=======================================================
二、從動(dòng)態(tài)頁(yè)的URL獲取相應(yīng)頁(yè)面內(nèi)容并寫入到文件
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;
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("執(zhí)行時(shí)間:"+ttime +"秒");
}
return htmlCode;
}
//存儲(chǔ)文件
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,把服務(wù)器返回的JSP響應(yīng)輸出到我們自己的Response中,就可以將響應(yīng)快速寫入Html文件,然后再發(fā)送給客戶。
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實(shí)現(xiàn)靜態(tài)HTML緩沖(一種折中方法)
緩沖是Web應(yīng)用中必須考慮的一個(gè)提高性能的重要手段。對(duì)于基于JSP/Servlet技術(shù)的站點(diǎn),常用的緩沖有持久層的數(shù)據(jù)庫(kù)連接池緩沖,內(nèi)存中的值對(duì)象緩沖,JSP頁(yè)面緩沖,以及各種各樣的緩沖框架等等,無(wú)不是為了提高系統(tǒng)的吞吐量。
然而對(duì)于大型站點(diǎn)來(lái)說(shuō),將JSP頁(yè)面轉(zhuǎn)換為靜態(tài)Html也許是最高效的方法,特別適合于數(shù)據(jù)不經(jīng)常變化但是頁(yè)面訪問(wèn)量特別大的站點(diǎn),如新聞等,通過(guò)把JSP動(dòng)態(tài)頁(yè)面預(yù)先轉(zhuǎn)換為靜態(tài)Html頁(yè)面,當(dāng)用戶請(qǐng)求此頁(yè)面時(shí),系統(tǒng)自動(dòng)導(dǎo)向到對(duì)應(yīng)的Html頁(yè)面,從而避免解析JSP請(qǐng)求,調(diào)用后臺(tái)邏輯以及訪問(wèn)數(shù)據(jù)庫(kù)等操作所帶來(lái)的巨大開(kāi)銷。
如何將一個(gè)已有的JSP站點(diǎn)的動(dòng)態(tài)JSP頁(yè)面轉(zhuǎn)化為靜態(tài)Html呢?我們希望在不用更改現(xiàn)有Servlet,JSP的前提下讓系統(tǒng)自動(dòng)將這些JSP轉(zhuǎn)換為Html頁(yè)。幸運(yùn)的是,F(xiàn)ilter為我們提供了一種實(shí)現(xiàn)方案。
Filter是Servlet 2.2規(guī)范中最激動(dòng)人心的特性。Filter能過(guò)濾特定URL如/admin/*并進(jìn)行必要的預(yù)處理,如修改Request和Response,從而實(shí)現(xiàn)定制的輸入輸出。更強(qiáng)大的是,F(xiàn)ilter本身是一個(gè)責(zé)任鏈模式,它能一個(gè)接一個(gè)地傳遞下去,從而將實(shí)現(xiàn)不同功能的Filter串起來(lái),并且可以動(dòng)態(tài)組合。
要自動(dòng)生成靜態(tài)頁(yè)面,用Filter截獲jsp請(qǐng)求并先進(jìn)行預(yù)處理,自動(dòng)生成Html,是個(gè)不錯(cuò)的主意。一個(gè)很容易想到的方法是在Filter截獲Request后,導(dǎo)向一個(gè)Servlet,在這個(gè)Servlet中向本機(jī)發(fā)送一個(gè)http請(qǐng)求,然后將響應(yīng)寫入一個(gè)文件:
URLConnection urlConn = URLConnection.open(http://localhost/req);
注意要避免遞歸。
另一個(gè)方法是不模擬http,而是定制Response,把服務(wù)器返回的JSP響應(yīng)輸出到我們自己的Response中,就可以將響應(yīng)快速寫入Html文件,然后再發(fā)送給客戶。而且,由于沒(méi)有http模擬請(qǐng)求,直接讀取服務(wù)器響應(yīng)速度非???。
截獲Response的關(guān)鍵便是實(shí)現(xiàn)一個(gè)WrappedResponse,讓服務(wù)器將響應(yīng)寫入我們的WrappedResponse中。這類似于一個(gè)代理模式,Servlet 2.x已經(jīng)提供了一個(gè)WrappedResponse類,我們只需要復(fù)寫其中的一些關(guān)鍵方法即可。
WrappedResponse實(shí)現(xiàn)了Response接口,它需要一個(gè)Response作為構(gòu)造函數(shù)的參數(shù),事實(shí)上這正是代理模式的應(yīng)用:WrappedResponse充當(dāng)了代理角色,它會(huì)將JSP/Servlet容器的某些方法調(diào)用進(jìn)行預(yù)處理,我們需要實(shí)現(xiàn)自己的方法。
綜上:用Filter實(shí)現(xiàn)HTML緩沖的步驟是:
1. 用Filter截獲請(qǐng)求,如/a.jsp?id=123,映射到對(duì)應(yīng)的html文件名為/html/a.jsp$id=123.htm。
2. 查找是否有/html/a.jsp$id=123.htm,如果有,直接forward到此html,結(jié)束。
3. 如果沒(méi)有,實(shí)現(xiàn)一個(gè)WrappedResponse,然后調(diào)用filterChain(request, wrappedResponse)。
4. 將返回的WrappedResponse寫入文件/html/a.jsp$id=123.htm,然后返回響應(yīng)給用戶。
5. 下一次用戶發(fā)送相同的請(qǐng)求時(shí),到第2步就結(jié)束了。
使用這個(gè)方法的好處是不用更改現(xiàn)有的Servlet,JSP頁(yè),限制是,JSP頁(yè)面結(jié)果不能與Session相關(guān),需要登陸或用戶定制的頁(yè)面不能用這種方法緩沖
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。