zoukankan      html  css  js  c++  java
  • 通过动态包含和Ajax机制抽取Web应用的公共页面

    在Java Web应用开发中,经常遇到的一种情况是,许多的页面中都包含着“公共页面”,这部分动态页面的特征是:访问量大,会带来较大的性能压力。功能设计上会动态地改变自身的元素。比如在登录前和登录后所展示的页面有所不同,比如以下代码:

     1 <div class="col-md-3" style="padding-top:20px">
     2                     <ol class="list-inline">
     3                     <%-- 根据Session中的loginUser是否为空, 来判断展示的内容 --%>
     4                       <c:if test="${empty loginUser}">                    
     5                         <li><a href="${pageContext.request.contextPath}/UserServlet?method=loginUI">登录</a></li>
     6                         <li><a href="${pageContext.request.contextPath}/UserServlet?method=registUI">注册</a></li>
     7                       </c:if>
     8                         
     9                       <c:if test="${not empty loginUser}">
    10                         <li>欢迎${loginUser.username}</li>
    11                         <li><a href="${pageContext.request.contextPath}/UserServlet?method=logOut">退出</a></li>
    12                         <li><a href="${pageContext.request.contextPath}/jsp/cart.jsp">购物车</a></li>
    13                         <li><a href="${pageContext.request.contextPath}/jsp/order_list.jsp">我的订单</a></li>
    14                       </c:if>    
    15                         
    16                     </ol>
    17                 </div>

    这是一段前端JSP代码,实现的是根据服务器处理登录功能后,session对象中的loginUser值是否为空,来判断是否登录完成,从而决定显示哪一段的标签内容。

    事实上,因为这是一段顶层页面的公共菜单栏,从而在成百上千的网页中都包括这段代码。如果每个页面都要更改这是不可想象的。

    解决的方法是通过动态包含机制来解决。

    相关的Java开发技巧可见:

    Java Servlet开发的轻量级MVC框架最佳实践

    以用户注册功能模块为例浅谈MVC架构下的JavaWeb开发流程

    静态包含和动态包含

    以JSP为例说明页面的静态包含和动态包含

    JSP中有两种包含:

    静态包含:<%@include file="被包含页面"%>

    动态包含:<jsp:include page="被包含页面"flush="true">。下面以一个例子来说明如何使用包含。

    实例
    项目文件树:

    header.jsp文件中内容:

    1 <html>
    2 <head>
    3 <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
    4 <title>Insert title here</title>
    5 </head>
    6 <body>
    7 <h1>This is header</</h1>

    content.jsp文件中内容

     1 <table border="1">
     2 <tr>
     3 <td>col1</td>
     4 <td>col2</td>
     5 </tr>
     6 <tr>
     7 <td>col1</td>
     8 <td>col2</td>
     9 </tr>
    10 </table>

    footer.jsp文件中内容:

    1 <hr>
    2 copyright: 1999-2010
    3 </body>
    4 </html>

    静态包含:
    index.jsp文件中内容:

    1 <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
    2 <%@ include file="/header.jsp" %>
    3 <%@ include file="/content.jsp" %>
    4 <%@ include file="/footer.jsp" %>

    页面显示结果:

    被编译成的java文件:

    动态包含

    index.jsp文件中内容:

    1 <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
    2 <jsp:include page="/header.jsp"></jsp:include>
    3 <jsp:include page="/content.jsp"></jsp:include>
    4 <jsp:include page="/footer.jsp"></jsp:include>

    页面显示结果:

    被编译成的java文件:

    这个例子说明,使用静态包含和动态包含最终的执行结果相同,但是实现过程不同,很明显编译成的java文件数目不同。

    静态和动态包含的区别与联系

    注:下文将包含有其它文件的jsp文件称为主体文件,比如上文中的index.jsp文件.将被包含的文件称为包含文件,比如上文中的header.jsp文件.

    1. <%@ include file="" %>是指令元素。<jsp:include page=""/>是行为元素
    2. 最终编译成java文件的数目不同。(从上面的例子可以看出)
      • 静态包含在转换成为java文件的时候将包含文件的内容“复制”到主体文件,然后作为一个整体编译。最终编译为一个java文件。
      • 动态包含是各个jsp文件分别转换,分别编译。最终编程成多个java文件。
    3. 执行时间不同
      • 静态包含发生在:JSP编译为java文件阶段。
      • 动态包含发生在:执行class文件阶段。动态加入。
    4. 静态包含在两个文件中不能有相同的变量,动态包含允许。
      • 由于静态包含相当于将包含文件内容直接复制到主体文件中,如果出现相同的变量,就会出现覆盖等问题,导致文件出错。而动态包含相当于调用不同的jsp,变量所在的空间不同,自然不会出现覆盖等现象。
    5. 无论是动态包含还是静态包含,其request对象都是相同的。也就是同一个request对象。
      • 静态包含最终编译成一个java文件,有一个request对象很好理解。而动态包含最终编译成多个jsp文件,为何会使用一个request对象呢?其实这些jsp组合的过程是一个请求转发的过程,自然也使用同一个request对象了。

    静态包含和动态包含的使用
    简单总结一下,就一句话:被包含的页面是静态页面就用静态包含,是动态页面就用动态包含。(当然不是很绝对,但是这样用没有错)

    Ajax动态获取公共页面元素的JSON格式数据

    公共页面,除了经常作为Header或Footer被多个页面引入外,更主要的是动态获取后台数据库Category数据作为菜单选项元素。在经典MVC架构中,这对应着一个Service和Dao服务如下:

    Servlet层

    1             CategoryService CategoryService=new CategoryServiceImp();
    2             List<Category> list = CategoryService.getAllCats();
    3             req.setAttribute("CatList", list);
    4             return "/jsp/info.jsp";

    Service层

    1     CategoryDao CategoryDao=new CategoryDaoImp();
    2     return CategoryDao.getAllCats();        

    Dao层

    1      String sql="select * from category";
    2         QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource());
    3         return qr.query(sql, new BeanListHandler<Category>(Category.class));

    但如果有成百上千的页面都需要用到这个公共页面,那就要在成百上千的交互中添加这段Servlet代码,这样的话代价很高。

    实践中主要是利用Ajax和Json格式来实现这样的菜单功能。

    基于JQuery的Ajax功能代码实现如下:

     1 $(function(){
     2     //向服务端CategoryServlet__>gteAllCats发起ajax请求,服务端经过处理,
     3     //将所有分类信息以JSON格式的数据返回,获取到返回的所有分类绑定在页面的显示分类区域
     4     var url="/ServletStoreDemo/CategoryServlet";
     5     var obj={"method":"findAllCats"};
     6     $.post(url,obj,function(data){
     7         //alert(data);
     8     
     9         //获取到服务端响应会的数据,经过观察data中存放的是一个JSON格式数组,遍历数组,动态的显示分类区域代码    
    10         $.each(data,function(i,obj){
    11             var li="<li><a href='#'>"+obj.cname+"</a></li>";
    12             $("#myUL").append(li);
    13         });
    14         
    15     },"json");
    16     
    17 });

    同时在CategoryServlet中,将数据库返回的数据,包装成JSON格式返回到客户端浏览器

    1 jsonStr=JSONArray.fromObject(list).toString();
    2 //将全部分类信息响应到客户端
    3 //告诉浏览器本次响应的数据是JSON格式的字符串
    4 resp.setContentType("application/json;charset=utf-8");
    5 resp.getWriter().print(jsonStr);

    原理解析

    1. 页面加载后,Ajax会向服务端CategoryServlet发起请求,触发getAllCats方法,服务端会处理该方法。

    2. 服务端查询数据库,将所有分类信息以JSON格式的数据返回。前端获取到返回的所有分类,通过使用匿名函数,绑定分类数据到页面的显示分类区域。

    3. 对获取的JSON格式数组进行遍历数组,动态的展示分类区域代码。

    通过使用Redis缓存,可以大幅提高首页访问的性能,在以后的博文中将介绍其原理。
     
  • 相关阅读:
    AcWing 1027. 方格取数 dp
    AcWing 1014. 登山 dp
    acwing 482. 合唱队形 dp
    LeetCode 1463. 摘樱桃II dp
    LeetCode 100. 相同的树 树的遍历
    LeetCode 336. 回文对 哈希
    LeetCode 815. 公交路线 最短路 哈希
    算法问题实战策略 DARPA大挑战 二分
    算法问题实战策略 LUNCHBOX 贪心
    AcWing 1100. 抓住那头牛 BFS
  • 原文地址:https://www.cnblogs.com/leoliu168/p/9988425.html
Copyright © 2011-2022 走看看