注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

古城风~~~

竹密无妨溪水过,天高不碍白云飞。这天下总有一份是属于我古城的天地!

 
 
 

日志

 
 

JSP页面静态化总结之二重写JspWriter与采用模版  

2009-09-23 14:30:50|  分类: java/jsp |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

2.1 Tomcat解析后的JSP结构分析
从一开始学习Jsp的时候,老师就给我们讲其实JSP最后也是被转变为Servlet运行的,其源代码可以在Tomcat的work目录中找到。这里我们来分析一下由JSP生成的代码
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;

public class test$jsp extends HttpJspBase {

    static {
    }
    public testOutRedir$jsp( ) {
    }

    private static boolean _jspx_inited = false;

    public final void _jspx_init() throws org.apache.jasper.runtime.JspException {
    }
   
//主要的方法
    public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

        JspFactory _jspxFactory = null;
        PageContext pageContext = null;
        HttpSession session = null;
        ServletContext application = null;
        ServletConfig config = null;
        JspWriter out = null;//主要靠JSPWriter输出
        Object page = this;
        String _value = null;
        try {

            if (_jspx_inited == false) {
                synchronized (this) {
                    if (_jspx_inited == false) {
                        _jspx_init();
                        _jspx_inited = true;
                    }
                }
            }
            _jspxFactory = JspFactory.getDefaultFactory();
            response.setContentType(text/html;charset=GB2312);
            pageContext = _jspxFactory.getPageContext(this, request, response,
                            , true, 8192, true);

            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();
                //为了节省篇幅,我删除了解释器添加的注释
                out.write(\r\n);
//上一句是由于后面的换行产生的
                out.write();
                out.write(\r\n\r\n\r\n\r\n);
                out.print( 输出 );
                out.write(\r\n\r\n\r\n\r\n);
        } catch (Throwable t) {
            if (out != null && out.getBufferSize() != 0)
                out.clearBuffer();
            if (pageContext != null) pageContext.handlePageException(t);
        } finally {
            if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
        }
    }
}

2.2 核心代码
由此可见,主要由JspWriter将最终的数据流通过HTTP传送到用户浏览器端。而页面静态化时,我们需要将最终的HTML页面存于服务器端,因些我们需要自己再编写一个类,使其继承于JspWriter以生成HTML文件。具体代码见下表:
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.jsp.JspWriter;

public class ConstPageWriter extends JspWriter {

private PrintWriter pw;

public ConstPageWriter(String fileName) {
   super(JspWriter.DEFAULT_BUFFER, false);
   try {
    File f =new File(fileName);
    //System.out.println(fileName);
    /*
    java.io.WinNTFileSystem.createFileExclusively
    解决办法是先创建目录。然后创建文件。
    */
    if(!f.exists()) f.createNewFile();
    pw = new PrintWriter(fileName, "UTF-8");
   } catch (Exception e) {
    e.printStackTrace();
   }
}

后面省略,全是实现抽象方法。

在需要静态化的页面中加入如下代码:
<%
String fileName = "html/"+"testindex.html";   // 生成的静态页面文件名
boolean notNeedUpdate =false; //从后台传进来,或者前台定义生成后修改
if (notNeedUpdate){                 // 判断是否需要更新
     response.sendRedirect(fileName);
     return;
}

out = new ConstPageWriter(pageContext.getServletContext().getRealPath(fileName));
%>
用自定义的out,即JspWriter代替默认的out.因此这一部分应当放在页面的开始,以便从一开始就采用了该对象。

后面接主体部分内容。

<%
out.close();
response.sendRedirect(fileName);
%>

通过以上的代码及实现了将动态的JSP页面转换为静态页面。主要是将输出流由HTTP流定向到了文件流上。
2.3 思考小结
该方式满足了以下几种静态化需求:
(1)单纯的JSP,即只由JSP负责处理业务的。通过该方式先将notNeedUpdate置为false静态化后再置为True,或者需要修改时置为True.
(2)经过Servlet跳转。经过Servlet跳转生成的页面,需要制定静态页面命名规则,即判断请求是否生成了以及是否需求生成静态页面。在后态判断notNeedUpdate值,不需要更新的后台业务逻辑也中止,直接跳转到该JSP,再由该JSP查找到静态页面,或者直接跳转到该HTML页面。

不过通过这种方式似乎在流程上走了一些弯路,处理了一些不必要的流程,同时管理起来也比较复杂,而且对原代码结构也进行了修改(需要后台支持,每个Servlet或者Action基本上都需要修改),整个的工作量大。另外更新HTML页面还有一种方式即删除原有的HTML页面,直接达到更新。采用这种方式,可以考虑将整个网站页面通过数据库管理起来,采用后台指定更新,这样似乎又可以方便进行管理,对一些CMS十分有用。

3 替换模版
对每一个JSP页面建立一个模板页面,将需要变动的数据作好标记,为每个标记替换文本。下面是一个简单的示例:
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());
}
%>
这种实现方式与前面的重写JspWriter类似,只不过更为复杂了些。

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>

这种方式的一些思考和前面采用JspWriter类似。

  评论这张
 
阅读(1546)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017