什么是页面静态化?
页面静态化就是把动态页面生成的html保存到服务器的文件上,然后有相同的请求时,不再去执行动态页面,而是直接给用户相应上次已经生成的静态页面。
项目案例
通过一个图书馆管理小项目来演示。
页面:
link.jsp:页面链接:
- 查询所有
- 查询SE分类
- 查询EE分类
- 查询框架分类
show.jsp:显示查询结果
Servlet
BookServlet
- fndAll()查看所有图书
- findByCategory() 按分类进行查询
BookDao: 操作数据库
重点记录一下,如何实现页面静态化。
通过一个过滤器,把BookServlet请求的所有资源所作的输出保存到html中,重定向到html页面。第二次访问时,如果这个html已经存在,就直接重定向,不用再访问BookServlet
请求资源保存到html中,需要重写response(使用修饰者模式参考:设计模式—装饰者模式)
StaticResponse.java
/**
* 修饰response,将服务器输出给客户端的HTML输入到指定的HTML页面
*/
public class StaticResponse extends HttpServletResponseWrapper {
private PrintWriter pw;
/**
* path:文件路径
* @param response
* @param path
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
*/
public StaticResponse(HttpServletResponse response,String path)
throws FileNotFoundException, UnsupportedEncodingException {
super(response);
//创建一个与HTML在一起的流对象
pw=new PrintWriter(path,"utf-8");
}
/**
* 重写getWriter()方法,直接返回我们自定义的PrintWriter对象:pw,不调用底层方法
* @return
* @throws IOException
*/
@Override
public PrintWriter getWriter() throws IOException {
return pw;
}
}
这里我们继承了 HttpServletResponseWrapper类,这个类帮我们实现了依靠底层对象的方法,我们自需要重写需要增强的方法即可。
接着是过滤器:StaticFiter.java
@WebFilter(filterName = "StaticFilter",urlPatterns = "/BookServlet")
public class StaticFilter implements Filter {
private FilterConfig config;
public void destroy() {
}
/**
* 把servlet请求的内容,保存到对应的页面中,
* 如果页面存在就直接重定向到对应的页面,如果不存在,就创建。
* @param req
* @param resp
* @param chain
* @throws ServletException
* @throws IOException
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//将request和response转化成httpServlet对应
HttpServletRequest request= (HttpServletRequest) req;
HttpServletResponse response= (HttpServletResponse) resp;
response.setContentType("text/html;charset=utf-8");
//获取请求类型参数
String category=request.getParameter("category");
/**
* 在web目录下建立一个html文件夹,保存html页面
* 1、获得html文件夹的路径,得到对应的需要的文件,判断文件是否存在
* 2、如果存在,重定项到该文件
* 3、如果不存在就创建,并重定项到该文件
* 文件名:null.html\1.html\2.html\3.html
*
*/
ServletContext servletContext=config.getServletContext();
String htmlPath=servletContext.getRealPath("/html");
String htmlName=category+".html";
//得到对应文件
File file=new File(htmlPath,htmlName);
if(file.exists()){//如果文件存在
//重定项
response.sendRedirect(request.getContextPath()+"/html/"+htmlName);
return;
}
//创建自定义response对象
StaticResponse sr=new StaticResponse(response,file.getAbsolutePath());
//方向自己写的response,创建对应页面
chain.doFilter(req, sr);
//重定项
response.sendRedirect(request.getContextPath()+"/html/"+htmlName);
}
public void init(FilterConfig config) throws ServletException {
this.config=config;
}
}
项目中,我们将html文件发在web目录下的html文件夹下。
在页面编码上注意:添加,否则页面传递到客户端乱码<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<title>图书信息</title>
</head>
<body>
<h1 align="center">图书信息</h1>
<table align="center" border="1" width="%50">
<tr>
<th>书名</th>
<th>单价</th>
<th>类别</th>
</tr>
<c:forEach items="${requestScope.bookList}" var="book">
<tr>
<td>${book.bname}</td>
<td>${book.price}</td>
<c:choose>
<c:when test="${book.category eq 1}"><td style="color: red">JavaSE</td></c:when>
<c:when test="${book.category eq 2}"><td style="color: blue">JavaEE</td></c:when>
<c:when test="${book.category eq 3}"><td style="color: green">JavaFramework</td></c:when>
</c:choose>
</tr>
</c:forEach>
</table>
</body>
</html>