过滤器实现页面静态化

页面静态化就是把每次都需要从数据库或者从别的网页抓取的内容存储到本地服务器,提高访问的速度。
要实现页面静态化有两个关键问题:
第一个就是如何把将动态页面存储到服务器。
第二个就是如何让请求转发到静态页面。

先来解决第一个问题,如何将动态页面存储到服务器。先给出代码:

public class StaticPageResponse extends HttpServletResponseWrapper{
    private PrintWriter pw;

    public StaticPageResponse(HttpServletResponse response, String filepath)
            throws IOException {
        super(response);
        //使用路径创建流!当使用该流写数据时,数据会写入到指定路径的文件中。
        File file = new File(filepath);
        File dir = file.getParentFile();
        if (!dir.exists()) {
            dir.mkdirs();
        }
        file.createNewFile();

        pw = new PrintWriter(file, "UTF-8");
    }

    //jsp页面会调用本方法获取这个流!使用它来写入页面中的数据。这些数据都写入到指定路径的页面中去了,即写入到静态页面中。
    public PrintWriter getWriter() throws IOException {
        return pw;
    }

    //刷新流,使缓冲区中的数据也写入到目标!
    public void close() throws IOException {
        pw.close();
    }}

我们都知道,jsp页面最终都讲编译成Servlet,然后Servlet中会调用Response的getWriter()方法获取PrintWriter对象,最后将页面内容打印到浏览器上,即:

PrintWriter out = response.getWriter();
out.print("<html>");
out.print("<head>");
...

我们现在需要的不是将页面内容打印到浏览器,而是将页面内容存储到服务器中保存,这样我们就需要将Response里面的getWriter()方法进行改写,使得out.print("...") 将页面内容保存到服务器而不是打印到浏览器中显示。怎么实现?

HttpServletResponseWrapper是HttpServletResponse的一个包装类,为HttpServletResponse接口的所有方法都提供了空实现。这个类的好处就是当我们需要实现HttpServletResponse接口以实现我们自己的一些功能时,我们只需要重写我们需要的方法,不需要为HttpServletResponse的每一个方法提供实现(若不能理解,可以实现HttpServletResponse接口尝试一下)。对应代码:

public class StaticPageResponse extends HttpServletResponseWrapper

PrintWriter这个类,构造函数中传入文件路径的话,调用这个方法的print()方法,使用该流写数据时,数据会写入到指定路径的文件中。对应代码:

pw = new PrintWriter(file, "UTF-8");

由此,我们就解决了第一个问题,当使用:

PrintWriter out = response.getWriter();
out.print("...");

时,页面内容将不会在浏览器中显示,而是保存到我们指定的文件路径中。

第二个问题:如何让请求转发到静态页面。先给出代码:

public class StaticFilter implements Filter {
    private ServletContext sc;

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        String key = "key_" + request.getParameter("category");//获取分类参数,分类参数可能是:1,2,3,null。使用分类参数做key

        Map<String,String> map = (Map<String, String>) sc.getAttribute("pages");//在ServletContext中获取Map,首次访问这个Map不存在。
        if(map == null) {
            map = new HashMap<String,String>();
            sc.setAttribute("pages", map);
        }//如果Map不存在,那么创建一个Map,并存放到ServletContext中,这样下次访问Map就存在了。

        if(map.containsKey(key)) {
            res.sendRedirect(req.getContextPath() + "/staticPages/" + map.get(key));
            return;
        }//查看Map中是否存在这个key,如果存在,那么获取值,值就是这个参数对应的静态页面路径。然后直接重定向到静态页面!

        String html = key + ".html";[如果当前请求参数对应的静态页面不存在,那么就生成静态页面,首先静态页面的名称为key,容颜名为html]
        String realPath = sc.getRealPath("/staticPages/" + html);//生成真实路径,下面会使用这个路径创建静态页面。
        StaticPagesResponse sr = new StaticPagesResponse (res, realPath);//创建自定义的response对象,传递待生成的静态页面路径
        chain.doFilter(request, sr);//放行
        sr.close();//这个方法的作用是刷新缓冲区!

        res.sendRedirect(req.getContextPath() + "/staticPages/" + html);//这时静态页面已经生成,重定向到静态页面
        map.put(key, html);//把静态页面保存到map中,下次访问时,直接从map中获取静态页面,不用再次生成。
    }

    public void init(FilterConfig fConfig) throws ServletException {
        this.sc = fConfig.getServletContext();
    }
}

这段代码主要的意思为:当第一次发出请求的时候,此时本地服务器上还没有静态页面,因此需要获取页面。然后将动态页面保存到服务器,最后将请求转发到静态页面即可。当再次请求同一资源时,此时服务器上已经有了静态页面,只需要将请求重定向到静态页面即可。
主要需要解决的小问题为:
1、拦截请求
2、怎样判断服务器是否有需要的静态页面

第一个小问题自然是使用过滤器。
第二个问题:
我们在ServletContext中定义一个Map类型的变量map, 使用某一个请求参数作key,对应的静态路径作value。

String key = "key_" + request.getParameter("category"); 

Map<String,String> map = (Map<String, String>) 
sc.getAttribute("pages")

当我们拦截到一个请求时,获取其请求参数,然后查找我们的map中是否有这样一个key,如果有我们就将请求重定向到这个key对应的value中。如果没有这样一个key,说明服务器中没有该静态资源,需要先获取,再重定向。

StaticPagesResponse sr = new StaticPagesResponse(res, realPath);
chain.doFilter(request, sr)

这段代码就是使用之前定义的经过改写的Response类。

至此,第二个问题也解决了。

需要注意页面的编码问题,很容易出现乱码,可以参考
http://boyadn.blog.163.com/blog/static/74230736201022655121696/

以上思路来自于我学习javaweb时,看的传智播客的崔希凡老师的教学视频。在做项目时运用到了,所以整理出来。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值