5.页面静态化

  • 当以MVC方式实现之前的例子内容查看页时,每次查看都要查询数据库、模板替换、然后生成HTML ,当并发人数较多时,会给服务器带来显著压力。

内容一旦录入,存储到数据库,后期应该一般不再变化, 既然内容不变,何不生成一个静态的页面呢? 特点:一次写入,多次读取 )。所以,本例不再使用伪静态方式,而是直接就生成静态的HTML文件,每次直接访问生成的静态页面。

首先写一个类HtmlGen.java,用于生成静态html文件

package statichtml;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;

public class HtmlGen
{
	// 全局实例
	public static HtmlGen i = new HtmlGen();
	
	protected Configuration frmkConfig;
	protected File appDir;
	
	// appDir : 模板文件所在目录 ( app所在目录 )
	// 注: 可以在BootLoader(Filter) 里初始化这个对象
	public synchronized void init(File appDir)
	{
		if(this.appDir != null) return; // 只初始化一次
		
		// 初始化
		this.appDir = appDir;
		try{
			frmkConfig = new Configuration(Configuration.VERSION_2_3_28);
			frmkConfig.setDirectoryForTemplateLoading(appDir); // 设置模板根目录
			frmkConfig.setDefaultEncoding("UTF-8");
			frmkConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			frmkConfig.setLogTemplateExceptions(false);
		}
		catch(Exception e)
		{		
			System.out.println("This Should Not Happen!");
		}
	}
	
	public void generate(String template, Object model, Writer out)throws Exception
	{
		if(appDir == null)
			throw new Exception("你忘记调用init()了! 请在BootLoader里初始化!");
		
		Template tp = frmkConfig.getTemplate(template); 
		tp.process(model, out);
	}
	
	// template : 模板文件
	// model: 数据
	// outPath: 生成的html文件路劲(相对于appDir)
	public void generate(String template, Object model, String htmlPath)throws Exception
	{
		File htmlFile = new File(appDir, htmlPath);
		Writer out = new FileWriter(htmlFile);
		try{
			Template tp = frmkConfig.getTemplate(template); 
			generate(template, model, out);
		}
		finally{
			// 确保文件句柄被关闭
			try{ out.close();}catch(Exception e){}
		}		
	}	
	
}

然后写一个Filter,BootLoader.java,在filter的init()方法里,初始化加载HtmlGen。

package statichtml;

import java.io.File;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter()
public class BootLoader implements Filter
{
	public void init(FilterConfig fConfig) throws ServletException
	{
		// 系统初始化都放在这里
		File appDir = new File(fConfig.getServletContext().getRealPath("/"));
		HtmlGen.i.init(appDir);
	}
	
	public void destroy()
	{
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException
	{
		chain.doFilter(request, response);
	}
}

在保存文章的时候,我们存储到数据库,并且生成一份静态的html文件,使用HtmlGen的generate(String template, Object model, String htmlPath)方法

@WebServlet("/PoemSave.api")
public class PoemSaveApi extends HttpServlet
{

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		// 读取请求数据, 转成字符串
		String reqText = readAsText(request.getInputStream(), "UTF-8");
		JSONObject jreq=new JSONObject(reqText);
		String title=jreq.getString("title");
		String author=jreq.getString("author");
		String dynasty=jreq.getString("dynasty");
		String content=jreq.getString("content");
		
		Poem poem=new Poem();
		poem.setTitle(title);
		poem.setAuthor(author);
		poem.setDynasty(dynasty);
		poem.setContent(content);
		
		try (SqlSession sqlSession = db.MyBatis.sqlSessionFactory.openSession())
		{
			sqlSession.insert("ls.test.insertPoem", poem);
			sqlSession.commit();
		}
		
		Map<String,Object> model=new HashMap<String,Object>();
		model.put("poem", poem);
		
		try
		{
			//生成静态html文件到 pages/n.html
			HtmlGen.i.generate("poem/view.html", model, "pages/"+poem.getId()+".html");
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		
		JSONObject jresp=new JSONObject();
		jresp.put("error", 0);
		jresp.put("reason","OK");
		//返回应答
		response.setContentType("text/plain");
		response.setCharacterEncoding("utf-8");
		Writer writer = response.getWriter();
		writer.write( jresp.toString(2));
		writer.close();		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}
	
	//这个方法实现的功能就是从InputStream里读取数据转成字符串
	public String readAsText(InputStream streamIn, String charset)
			throws IOException 
	{
		ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16);  
        byte[] data = new byte[1024];  
        while (true)
        {
        	int n = streamIn.read(data); // n: 实际读取的字节数
        	if(n < 0) break; // 连接已经断开
        	if(n == 0) continue; // 数据未完 // TODO: 要防止超时 

        	// 缓存起来
        	cache.write(data, 0, n);        	
        	if(cache.size() > 1024*512) // 上限, 最多读取512K
        		break;
        }  
        
        return cache.toString(charset);
	}

}

之后访问  http://127.0.0.1:8080/demo/pages/n.html  访问的就是生成的静态的html页面了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值