在JSP中,指令(directive)控制JSP编译器生成Servlet的行为,它能够设置JSP页面相关的属性以及控制生成HTML内容。之前我们已经接触过不少指令,例如:
<%@ page import="java.util.*" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
指令以<%@ directive attribute="value" %>
的形式存在于JSP源文件中,其中directive
可以是三种类型之一:
page
——定义页面的属性,例如使用哪种语言(language
属性)、页面的contentType
以及编码方式(encoding
)、导入哪些包(import
)taglib
——标签库指令描述了要使用的JSP标签库。该指令需要指定一个前缀prefix(和C++的命名空间很类似)和标签库的描述URI。JSTL是Java EE规范中定义的标准标签库,它需要通过标签库指令引用后才能在JSP文件中使用。include
——告知JSP编译器把另外一个文件内容完全包含至当前JSP文件中。效果就好像被包含文件的内容直接被粘贴到当前文件中一样,和C语言的预处理器非常类似。JSP动作(Action)是在JSP执行处理阶段完成特定功能的标签。
和JSP指令元素不同的是,它是在请求处理阶段执行的,而指令则是在编译阶段被执行。
利用JSP动作可以动态地包含其他文件、重定向页面等等,其中最常用的当属<jsp:include>
,它与包含指令的区别将会在下文提及。
如果要在页面中forward到另外一个页面,则可以使用<jsp:forward>
动作。
关于JavaBean的操作有三个JSP动作,包括:
<jsp:useBean>
:查找或者实例化一个JavaBean<jsp:setProperty>
:设置JavaBean的属性<jsp:getProperty>
:输出某个JavaBean的属性实际上访问JavaBean信息,使用JSTL+EL表达式已经足以应付大部分情况,这几个动作我们不做详细介绍。
更多关于JSP动作请参考这里。
包含指令能够把另外一个文件内容完全包含至当前JSP文件中,这是一种非常常用的组织页面的方式。在大多数网站中,不同的页面之中一定会存在公共的部分,例如博客系统的导航栏、底部版权声明。如果在每一个JSP页面中都重复的编写一次显然是不可取的,那么通过JSP的包含指令将这些公共的内容抽取在单独的JSP文件中,既减少了重复代码的数量,也提高了页面文件的维护性——只需要修改一处地方即可让所有包含它的页面生效。
以博客信息页面为例,你可以发现其中的很多信息与其它页面是一样的:
可以把这些公共部分独立成单独的JSP。
使用包含指令非常的简单,以博客底部版权声明为例,将页面中导航栏部分提取到一个单独的footer.jsp
中:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<footer>
© 2014 SomeCompany, Org · <a href="#">隐私</a> · <a href="#">条款</a>
</footer>
在需要引用它的JSP文件中,通过include
指令引入:
这里file
属性的值是相对于当前文件的相对路径,一般来说我们会将这些公共的JSP文件单独放在一个目录中,比如放在common
目录下,则:
<head>
标签中的各类静态资源定义,也可以发现所有页面都有一些共同的静态依赖资源,抽取出来如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
此时你只需针对特定页面,在<head></head>
增加自己独有的静态资源即可。
同样的道理,导航栏、用户信息和归档列表等也可以抽取到公共文件中。那么对于任意一个页面,它的结构是相对固定的:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<%@include file="common/head.jsp" %>
</head>
<body>
<%@include file="common/nav.jsp" %>
<%@include file="common/footer.jsp" %>
</body>
</html>
我们就可以在这个结构中增加页面的主体内容。
jsp:include
动作jsp:include
是JSP内置的一个动作标签,和JSP的包含指令很类似,它的作用同样是将其他JSP文件的内容包含至当前页面:
和包含指令不同的是,jsp:include
在每次请求当前JSP文件的时候,才将目标JSP文件包含进来(而包含指令则是在编译时)。
它还能够支持动态的引入:
<jsp:include page="file_name">
<jsp:param name="parameter_name" value="${parameter_value}" />
</jsp:include>
通过jsp:param
标签,可以将某个参数传给目标JSP文件。在目标JSP文件中,parameter_name
变量就可以像普通上下文中的变量一样被使用:${param.parameter_name}
。即目标JSP文件中的表达式中的变量值,可以通过jsp:param
标签传入。
注意在使用参数的页面中需要增加param
前缀。而且使用这种方式,只能进行字符串传参,如果需要传入对象,则可以使用<c:set>
标签:
这样在使用参数页面,就能通过类似${user.username}
这样的表达式来引用对象的属性了,而且不需要param
前缀。
由于这样的动态支持,jsp:include
动作能够支持更加灵活的场景,这是包含指令所不能做到的。针对包含指令和jsp:include
动作的特点,可以归纳出他们的使用场景:
<head>
部分的静态资源,页面底部信息)时,使用包含指令jsp:include动作
导航栏我们提取出来命名为nav
,导航栏要根据当前用户信息,确定是否显示管理菜单,这一部分公共内容抽如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="./blogs">${param.username == null ? "天码营":param.username}的博客</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="./blogs">首页</a></li>
<c:if test="${currentUser != null }">
<li><a href="./about">关于</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">账号管理
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-header">管理</li>
<li><a href="list.html">博客信息</a></li>
<li><a href="#">创建博文</a></li>
<li><a href="#">博客管理</a></li>
<li class="divider"></li>
<li class="dropdown-header">账号</li>
<li><a href="#">更改密码</a></li>
<li><a href="#">退出登录</a></li>
</ul>
</li>
</c:if>
</ul>
<form class="navbar-form navbar-right">
<div class="form-group">
<input type="text" class="form-control" placeholder="关键字">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
</div>
</div>
</nav>
注意这为了防止不存在${username}
变量的情况下,显示默认信息,使用了三目运算符${username == null ? "天码营":username}
。
<c:if test="${currentUser != null }">
用来判断${currentUser}
变量是否存在,存在则显示管理菜单。
在用户登陆的情况下,我们可以设置好currrentUser
变量,如何设置我们在后面的练习中完成。
进行引用的时候,如果当前页面存在${user}
变量,则可以将该变量传给nav.jsp
:
<jsp:include page="common/nav.jsp">
<jsp:param name="username" value="${user.username}" />
</jsp:include>
<jsp:param>
这一行代码表示向nav.jsp
页面传入username
参数。
如果将当前登陆用户信息存放在Session中,则这样传参:
<jsp:include page="common/nav.jsp">
<jsp:param name="user" value="${sessionScope.currentUser.username}" />
</jsp:include>
可见,通过jsp:param
传参,可以引用当前JSP页面中的变量,也可以引用当前Session中存储的变量。
登录发表评论 登录 注册