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

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

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

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

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

相关的Java开发技巧可见:

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

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

静态包含和动态包含

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

JSP中有两种包含:

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

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

实例
项目文件树:

header.jsp文件中内容:

 <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
<h1>This is header</</h1>

content.jsp文件中内容

 <table border="1">
<tr>
<td>col1</td>
<td>col2</td>
</tr>
<tr>
<td>col1</td>
<td>col2</td>
</tr>
</table>

footer.jsp文件中内容:

 <hr>
copyright: 1999-2010
</body>
</html>

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

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

页面显示结果:

被编译成的java文件:

动态包含

index.jsp文件中内容:

 <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<jsp:include page="/header.jsp"></jsp:include>
<jsp:include page="/content.jsp"></jsp:include>
<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层

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

Service层

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

Dao层

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

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

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

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

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

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

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

原理解析

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

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

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

通过使用Redis缓存,可以大幅提高首页访问的性能,在以后的博文中将介绍其原理。

 

通过动态包含和Ajax机制抽取Web应用的公共页面的更多相关文章

  1. java web jsp原理图 ,静态包含,动态包含,out与response.getWrite()

    jsp原理图 ,静态包含,动态包含,out与response.getWrite() 

  2. java Web jsp页面的静态包含和动态包含

    现在有头 体 尾 三个jsp页面 top.jsp <%@ page language="java" contentType="text/html; charset= ...

  3. Python基础篇【第3篇】: Python异常处理、反射、动态导入、利用反射的web框架

    异常处理 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当P ...

  4. 【Ajax 1】Ajax与传统Web开发的区别

    导读:从用户体验度的角度来说,利用Ajax进行开发的网站,其体验度高于利用传统Web开发技术,那么,是什么因素导致了这一现象呢?难道说Ajax开发,就一定优于传统Web技术吗?本篇文章,将主要介绍Aj ...

  5. MyBatis框架——动态SQL、缓存机制、逆向工程

    MyBatis框架--动态SQL.缓存机制.逆向工程 一.Dynamic SQL 为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句.最常用的就是:where和if标签 1.参考 ...

  6. JSP运行过程 JSP脚本 静态动态包含 jsp指令 jsp内置对象jsp四大作用域 jsp动作元素 EL表达式 JSTL 设计模式 JSP开发模式 EL内置对象

    Day38 JSP JSP的运行过程具体如下: (1)客户端发出请求,请求访问JSP文件. (2)JSP容器先将JSP文件转换成一个Java源文件(Java Servlet源程序),在转换过程中,如果 ...

  7. jsp-静态包含和动态包含的区别

    include指令是静态包含.静态包含的意思就是:把文件的代码内容都包含进来,再编译! include指令是静态包含,include行为是动态包含.其实include行为就是封装了request.ge ...

  8. 浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

    在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及 ...

  9. JSP中的动态包含和静态包含的区别

    本文转载自http://blog.csdn.net/xuxu198899223/article/details/8501044 1. 语法格式 (1)静态包含:<%@ include file= ...

随机推荐

  1. Python2.7-difflib

    difflib主要用于比较两个序列的不同,常见于字符串的比较,可以对差异生成报告.SequenceMatcher 主要用于找两者相似部分,以及两者不同的转换方法,而 Differ 更注重于比较两者的区 ...

  2. windows linux hosts文件的配置,开发项目中域名跳转等。

    我们通常都知道Windows中hosts文件(C:\Windows\System32\drivers\etc),用来映射域名的.linux上当然也有,一般在/etc/hosts下. 当工作的项目,在开 ...

  3. Exp2 MAL_后门原理与实践 20155214

    目录 Exp2 MAL_后门原理与实践 实验内容 通过nc反向连接创建后门 meterpreter应用 主要思路 知识点 启发 Exp2 MAL_后门原理与实践 本次实验操使用nc实现win,mac, ...

  4. Command and Query Responsibility分离模式

    CQRS模式,就是命令和查询责任分离模式. CQRS模式通过使用不同的接口来分离读取数据和更新数据的操作.CQRS模式可以最大化性能,扩展性以及安全性,还会为系统的持续演化提供更多的弹性,防止Upda ...

  5. 奔跑吧Linux

    刚拿到MiZ702,就被他的"外貌"深深的吸引,核心板加底板的形式让她看上去,强大而神秘-- 华丽的外表之下是否有着与之相当的内含呢,我们拿Linux将其检验一番! 板载的TF卡里 ...

  6. 【SP1812】LCS2 - Longest Common Substring II

    [SP1812]LCS2 - Longest Common Substring II 题面 洛谷 题解 你首先得会做这题. 然后就其实就很简单了, 你在每一个状态\(i\)打一个标记\(f[i]\)表 ...

  7. jQuery .attr() vs. .prop()

    Property vs. Attribute 在开始正式比较prop()和attr()两个jQuery方法之前,我们有必要先弄清一下Property和Attribute两个单词的意思.在中文里面,它们 ...

  8. 【ORACLE】oracle数据库用户密码复杂度配置

    -- 设置密码复杂度 SQL> @ /u01/app/oracle/product/11.2.0/db_1/rdbms/admin/utlpwdmg.sql -- 测试 SQL> alte ...

  9. Windows 10无法使用debug的解决方案

    在学习汇编语言的时候,XP系统或者更早版本的默认在Dos命令下敲入debug即可进入汇编指令模式下,而在Windows 7及更高版本下,这些功能似乎都被阉割了,所以今天我们讲带大家处理一下如何解决这个 ...

  10. Windows中的键盘快捷方式

    Windows 中的键盘快捷方式 适用于: Windows 10Windows 8.1Windows 7 Windows 10 键盘快捷方式就是按键或按键组合,可提供一种替代方式来执行通常使用鼠标执行 ...