我们可能都已经注意到了,访问诸如新浪这样的大型站点的新闻时,我们会发现每一篇文章都会对应一个静态的页面,以此方式在大量并发访问时减小数据库服务器的负担。刚开始做web应用程序时,对于这类需求感觉非常之难,且不知从何处着手。偶然的机会看到一个论坛上实现介绍这类应用实现原理的讨论,突然大悟,就试着实现了该应用,现在正是我工作还没着落的最不如意的时期,正好边学习,边整理曾经的学习笔记,避免以后用得着的时候笔记又丢失的无影无踪。
原理倒也简单:在页面中以编程的方式访问一篇文章,通过拦截响应内容并写入html文件。
使用方法:只需要在添加完文章代码之后:设置相关属性(加背景色的代码需要的属性),并且使用<jsp:include>元素或具有相同功能的代码访问servlet即可
注意:使用了文字背景的部分,使用时注意查看访问该servlet时是否设置了相关属性,否则servlet可能不能正常执行。
servlet 代码如下:
import java.io.*;
import java.net.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.http.*;
public class toHtml extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("GBK");
//测试表明:通过REFERER 可以在服务器段获得发送请求的页面完整的路径信息
String send_req_url =request.getHeader("REFERER");
//获取应用程序在服务器端文件系统的绝对路径
ServletContext context=getServletContext();
String rootRealPath=context.getRealPath("/");
String foldPath="/m/fy/fmd";//模板文件的目录结构
String modelName="/m_article.jsp";//模板文件的名字
//构造rootPath,形如:" http://localhost:8080/AjaxTrip"
String contextStr=request.getContextPath();
String urlStr=request.getRequestURL().toString();
String rootPath=urlStr.substring(0, urlStr.indexOf(contextStr))+contextStr;//" http://localhost:8080/AjaxTrip"
String htmlId=(String)request.getAttribute("htmlId");
String action=(String)request.getAttribute("action");
String queryStr=null;
//构造访问模板文件的url
String sourceUrl=rootPath+foldPath+modelName;
if("addArticle".equals(action)){
queryStr=(String)request.getAttribute("queryStr");
}
if(queryStr!=null){
sourceUrl=sourceUrl+"?"+queryStr;
}
/* JspToHtml :自定义类,实现依据当期日期生成响应的目录结构和文件:如:n/2009/1108/htmlId.html
* 并且提供了将响应内容写入文件的方法:
* */
JspToHtml jth=new JspToHtml();
jth.setUrl(rootRealPath);//设置io操作的绝对路径
//使用URL对象通过编程的方式访问指定的文章,读取响应内容保存到sTotalString中
String sCurrentLine="";
String sTotalString="";
InputStream l_urlStream ;
URL l_url=new URL(sourceUrl);
HttpURLConnection l_conn=(HttpURLConnection)l_url.openConnection();
l_conn.connect();
l_urlStream=l_conn.getInputStream();
BufferedReader l_reader=new BufferedReader(new InputStreamReader(l_urlStream,"utf-8"));
while((sCurrentLine=l_reader.readLine())!=null){
sTotalString+=sCurrentLine;
}
/*
* 向浏览器发送数据时,输出内容使用的默认字符集也不支持中文, 避免出现乱码,必须
* 在发送数据之前调用下面的方法设置响应内容的编码方式
* */
response.setContentType("text/html;charset=utf-8");
if(null!=htmlId){
//JspToHtml 调用相应方法创建html文件
boolean bool=jth.createHtml(sTotalString,htmlId);
request.setAttribute("htmlReady", "ok");
}else{
System.out.println("htmlId is null");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request,response);
}
}
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("GBK");
//测试表明:通过REFERER 可以在服务器段获得发送请求的页面完整的路径信息
String send_req_url =request.getHeader("REFERER");
//获取应用程序在服务器端文件系统的绝对路径
ServletContext context=getServletContext();
String rootRealPath=context.getRealPath("/");
String foldPath="/m/fy/fmd";//模板文件的目录结构
String modelName="/m_article.jsp";//模板文件的名字
//构造rootPath,形如:" http://localhost:8080/AjaxTrip"
String contextStr=request.getContextPath();
String urlStr=request.getRequestURL().toString();
String rootPath=urlStr.substring(0, urlStr.indexOf(contextStr))+contextStr;//" http://localhost:8080/AjaxTrip"
String htmlId=(String)request.getAttribute("htmlId");
String action=(String)request.getAttribute("action");
String queryStr=null;
//构造访问模板文件的url
String sourceUrl=rootPath+foldPath+modelName;
if("addArticle".equals(action)){
queryStr=(String)request.getAttribute("queryStr");
}
if(queryStr!=null){
sourceUrl=sourceUrl+"?"+queryStr;
}
/* JspToHtml :自定义类,实现依据当期日期生成响应的目录结构和文件:如:n/2009/1108/htmlId.html
* 并且提供了将响应内容写入文件的方法:
* */
JspToHtml jth=new JspToHtml();
jth.setUrl(rootRealPath);//设置io操作的绝对路径
//使用URL对象通过编程的方式访问指定的文章,读取响应内容保存到sTotalString中
String sCurrentLine="";
String sTotalString="";
InputStream l_urlStream ;
URL l_url=new URL(sourceUrl);
HttpURLConnection l_conn=(HttpURLConnection)l_url.openConnection();
l_conn.connect();
l_urlStream=l_conn.getInputStream();
BufferedReader l_reader=new BufferedReader(new InputStreamReader(l_urlStream,"utf-8"));
while((sCurrentLine=l_reader.readLine())!=null){
sTotalString+=sCurrentLine;
}
/*
* 向浏览器发送数据时,输出内容使用的默认字符集也不支持中文, 避免出现乱码,必须
* 在发送数据之前调用下面的方法设置响应内容的编码方式
* */
response.setContentType("text/html;charset=utf-8");
if(null!=htmlId){
//JspToHtml 调用相应方法创建html文件
boolean bool=jth.createHtml(sTotalString,htmlId);
request.setAttribute("htmlReady", "ok");
}else{
System.out.println("htmlId is null");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request,response);
}
}
===下面是辅助类:JspToHtml.java源代码
package com.java.yanjie.translate;
import java.util.*;
import java.io.*;
import java.text.*;
/*
* 使用该类注意事项:功能:封装对目录和文件的相关操作。
* 2:必须先调用setUrl()方法设置文件和目录操作的绝对路径,然后调用createHtml(String content,String id)
* 创建指定名称和内容的文件。创建的文件保存在如下格式的路径下:根目录/n/year/monthday/*.html
* 如:在2009-10-31 创建的文件位于:/n/2009/1031/id.html
*
*
* */
import java.util.*;
import java.io.*;
import java.text.*;
/*
* 使用该类注意事项:功能:封装对目录和文件的相关操作。
* 2:必须先调用setUrl()方法设置文件和目录操作的绝对路径,然后调用createHtml(String content,String id)
* 创建指定名称和内容的文件。创建的文件保存在如下格式的路径下:根目录/n/year/monthday/*.html
* 如:在2009-10-31 创建的文件位于:/n/2009/1031/id.html
*
*
* */
public class JspToHtml {
private String baseUrl="D:\\java_workspace\\AjaxTrip\\WebContent";
private String prefixFold=" \\n";
private String foldUrl;
/*
* 类的功能:封装对目录和文件的操作
* */
public JspToHtml(){
}
/*
* name:setUrl
* function:设置目录和文件操作的时使用的根路径(web应用程序的根文件夹的绝对路径)
* */
public void setUrl(String baseUrl){
this.baseUrl=baseUrl;
}
private String getBaseUrl(){
return baseUrl;
};
/*
* name:setFoldUrl
* function:设置文件目录结构字符串
* */
private void setFoldUrl(String fileUrl){
this.foldUrl=fileUrl;
}
private String getFoldUrl(){
return foldUrl;
}
private String getPrefixFold(){
return prefixFold;
}
/*
* name;createHtml
* function:创建html文件,内容是content,名称是id.html
*
* */
public boolean createHtml(String content,String id){
boolean bool=false;
String cont=content;
String id1=generateFileNameStr();
String fileName=id+".html";
FileWriter toFile;
BufferedWriter out;
try{
if(formatUrl()){
toFile=new FileWriter(getFoldUrl()+" \\"+fileName);
out=new BufferedWriter(toFile);
out.write(cont,0,cont.length());
out.close();
toFile.close();
bool=true;
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
return bool;
}//createHtml
/*
* name:deleteHtml
* function:删除指定id(文件名称去除后缀)的html文件
*
* */
public boolean deleteHtml(String htmlId){
boolean bool=false;
String name=htmlId;
if(htmlId==null){
return bool;
}
String yearStr=htmlId.substring(0, 4);
String monthDayStr=htmlId.substring(4,8);
String fileUrl=getBaseUrl()+getPrefixFold()+" \\"+yearStr+"\\"+monthDayStr+"\\"+htmlId+".html";
File file_del=new File(fileUrl);
if(file_del.exists()){
file_del.delete();
bool=true;//删除成功标志
}
return bool;
}
/*
* name:formatUrl
* function:检查当前日期的文件目录结构是否存在,若不存在,则创建对应的目录结构,并且若目录结构存在,
* 则保存该目录结构字符串 保存
*
* */
private String baseUrl="D:\\java_workspace\\AjaxTrip\\WebContent";
private String prefixFold=" \\n";
private String foldUrl;
/*
* 类的功能:封装对目录和文件的操作
* */
public JspToHtml(){
}
/*
* name:setUrl
* function:设置目录和文件操作的时使用的根路径(web应用程序的根文件夹的绝对路径)
* */
public void setUrl(String baseUrl){
this.baseUrl=baseUrl;
}
private String getBaseUrl(){
return baseUrl;
};
/*
* name:setFoldUrl
* function:设置文件目录结构字符串
* */
private void setFoldUrl(String fileUrl){
this.foldUrl=fileUrl;
}
private String getFoldUrl(){
return foldUrl;
}
private String getPrefixFold(){
return prefixFold;
}
/*
* name;createHtml
* function:创建html文件,内容是content,名称是id.html
*
* */
public boolean createHtml(String content,String id){
boolean bool=false;
String cont=content;
String id1=generateFileNameStr();
String fileName=id+".html";
FileWriter toFile;
BufferedWriter out;
try{
if(formatUrl()){
toFile=new FileWriter(getFoldUrl()+" \\"+fileName);
out=new BufferedWriter(toFile);
out.write(cont,0,cont.length());
out.close();
toFile.close();
bool=true;
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
return bool;
}//createHtml
/*
* name:deleteHtml
* function:删除指定id(文件名称去除后缀)的html文件
*
* */
public boolean deleteHtml(String htmlId){
boolean bool=false;
String name=htmlId;
if(htmlId==null){
return bool;
}
String yearStr=htmlId.substring(0, 4);
String monthDayStr=htmlId.substring(4,8);
String fileUrl=getBaseUrl()+getPrefixFold()+" \\"+yearStr+"\\"+monthDayStr+"\\"+htmlId+".html";
File file_del=new File(fileUrl);
if(file_del.exists()){
file_del.delete();
bool=true;//删除成功标志
}
return bool;
}
/*
* name:formatUrl
* function:检查当前日期的文件目录结构是否存在,若不存在,则创建对应的目录结构,并且若目录结构存在,
* 则保存该目录结构字符串 保存
*
* */
private boolean formatUrl(){
/*
如果存放当前日期文件的目录结构不存在,则创建对应的目录结构
* */
boolean bool=false;
File file=new File(getBaseUrl());
if(file.exists()&&file.isDirectory()){
String foldStr=getTodayFilePath();
File filePath=new File(foldStr);
if(!filePath.exists()){
filePath.mkdirs();
}
if(filePath.isDirectory()){
bool=true;
setFoldUrl(foldStr);
}
}
return bool;
}//formatUrl()
//存放*.html的目录结构: .../.../根目录/年/月日/*.html
/*
* name:getTodayFilePath
* function:该方法返回文件名之前的部分呢
* */
private String getTodayFilePath(){
String tPath="";
String dateStr[];
dateStr=new String[2];
String patternStr[]={"yyyy","MMdd"};
dateStr[0]=new SimpleDateFormat(patternStr[0]).format(new Date());
dateStr[1]=new SimpleDateFormat(patternStr[1]).format(new Date());
tPath=getBaseUrl()+getPrefixFold()+" \\"+dateStr[0]+"\\"+dateStr[1];
return tPath;
}
private String generateFileNameStr(){
String fileName="";
fileName=new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
return fileName;
}
/*
* main 方法测试类是否正常工作
*
* */
public static void main(String args[]){
JspToHtml jspToHtml=new JspToHtml();
jspToHtml.createHtml("aa", "11");
System.out.println("create html success!!");
jspToHtml.deleteHtml("20091031191355");
}
}
/*
如果存放当前日期文件的目录结构不存在,则创建对应的目录结构
* */
boolean bool=false;
File file=new File(getBaseUrl());
if(file.exists()&&file.isDirectory()){
String foldStr=getTodayFilePath();
File filePath=new File(foldStr);
if(!filePath.exists()){
filePath.mkdirs();
}
if(filePath.isDirectory()){
bool=true;
setFoldUrl(foldStr);
}
}
return bool;
}//formatUrl()
//存放*.html的目录结构: .../.../根目录/年/月日/*.html
/*
* name:getTodayFilePath
* function:该方法返回文件名之前的部分呢
* */
private String getTodayFilePath(){
String tPath="";
String dateStr[];
dateStr=new String[2];
String patternStr[]={"yyyy","MMdd"};
dateStr[0]=new SimpleDateFormat(patternStr[0]).format(new Date());
dateStr[1]=new SimpleDateFormat(patternStr[1]).format(new Date());
tPath=getBaseUrl()+getPrefixFold()+" \\"+dateStr[0]+"\\"+dateStr[1];
return tPath;
}
private String generateFileNameStr(){
String fileName="";
fileName=new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
return fileName;
}
/*
* main 方法测试类是否正常工作
*
* */
public static void main(String args[]){
JspToHtml jspToHtml=new JspToHtml();
jspToHtml.createHtml("aa", "11");
System.out.println("create html success!!");
jspToHtml.deleteHtml("20091031191355");
}
}
转载于:https://blog.51cto.com/hnsyj/224058