在学习JSP语法之前,我们需要知道JSP最终以servlet方式在容器中运行。下面是JSP转换为servlet的整个过程。
容器将JSP文件翻译成servlet类的源文件(.java),然后 将其编译成servlet class。
以和手工编写servlet同样的方式运行servle。

一 、 JSP基本语法
jsp基本语法由指令 、 表达式 、 声明三部分组成。
1 指令(directive )
一个JSP元素,用来给JSP容器一个说明,在翻译的时候 被解释。有三种JSP指令:page, include, taglib
1)page指令
定义与页面相关的属性,常见的有
import指令:定义将在生成的servlet类中添加的Java import语句。缺省情 况下自动加入:java.lang, javax.servlet, javax.servlet.http, javax.servlet.jsp.
contentType:定义JSP响应的MIME类型。
isErrorPage:定义当前的页面是否为另一个JSP页面的错误页面。 缺省值为“false”。如果值为“true”,页面可以访问隐 含的exception对象;否则不能访问。
language:定义在脚本、表达式和声明中使用的脚本语言,现在 其值只能为“java”
……..
利用使用import属性导入外部的包,通过<%@ ….. %>语法来表示。

2)include指令
定义一段文字或代码,它可以在当前页面被解析时加 入其中,增强了代码的复用性
1 | <%@ include file="header.html" %> //在当前位置插入header.html |
3) taglib指令
定义JSP可以使用的标签库.
1 | <%@ taglib tagdir=”/WEB-INF/tags/cool” prefix=”cool” %> //在当前jsp中使用tag标签 |
2. 表达式(expression)
表达式的基本语法是:<%= …. %>。
表达式在运行时转化成out.print()的参数,不能将返回值为void的方法作为表达式。

3. 声明(declaration)
声明的语法是 <% … %>,在声明中可以编写java代码。
在java代码片断(scriptlet)中定义的变量。
1 | <% int count = 0; %> //定义了一个本地变量count |
所有的java代码片断和表达式代码都在一个service方法 中,所以在java代码片断中声明的变量总是本地变量。
既然jsp声明的变量都是本地变量,也就是用户每次访问servlet这个变量都会被初始化。如果我们有这样一个需求,统计访问页面的人数count。这个count变量每次用户访问都会初始化为0,就无法统计访问次数了。此时我们需要在静态变量。
如何在jsp中定义静态变量呢?——使用 jsp声明
jsp声明语法是这样的 <%! …. %>。
用于声明生成的servlet类的成员,即变量和方法,<%!和%>间的部分将被添加到service方法之外,可以定义静态变量和方法。
- 定义变量

- 定义方法

二 、 jsp的优化
jsp页面上不仅可以写java的后台代码,也可以写一些html便签,虽然看似融合了逻辑处理和页面展示两大作用,但是这样不仅使得页面混乱,而且在jsp中的Java代码使其难于更改和维护。
此时出现了Action(JavaBean标准动作) 和 EL表达式 用来解决这一问题。接下来介绍一下 EL表达式 ,action不详述。
2.1 JavaBean标准动作
JavaBean标准动作是为了 消除JSP中的脚本(Java代码片断、声明、表 达式)。常用的标准动作有如下几种:
jsp:useBean 寻找或实例化一个JavaBean
jsp:getProperty 输出JavaBean的某个属性
jsp:setProperty 设置JavaBean的某个属性
2.2 EL 表达式
EL提供了一种调用Java代码的简单方法 ;可以部分地取代JSP中的Java代码片断和表达式 。
EL的语法是: ${ firstThing.secondThing }.
通常写在大括号中,前面加$符号
第一个变量是隐含对象或属性
1. EL 隐含对象是什么
隐含对象是 implicit object,为了能够获得web应用程序中的相关数据,EL表达式中定义了一些隐含的对象。这些对象共有11个。前10个都是Map对象,最后是一个javaBean对象。
隐含对象 | 对象类型 | 说明 |
---|---|---|
pageScope | java.util.Map | 表示变量只能在本页面使用。 |
requestScope | java.util.Map | 表示变量能在本次请求中使用。 |
sessionScope | java.util.Map | 表示变量能在本次会话中使用 |
applicationScope | java.util.Map | 表示变量能在整个应用程序中使用。 |
param | java.util.Map | 包含页面所有参数的名称和对应值的集合 |
paramValues | java.util.Map | 包含页面所有参数的名称和对应多个值的集合 |
header | java.util.Map | 包含每个header名和值的集合 |
headerValues | java.util.Map | 包含每个header名和可能的多个值的集合 |
cookie | java.util.Map | 包含每个cookie名和值的集合 |
initParam | java.util.Map | 包含Servlet上下文初始请求参数名和对应值的集合 |
pageContext | javax.servlet.jsp.PageContext | 用于访问jsp内置对象,是对pageContext对象 的引用(pageContext 是一个JavaBean |
2. 操作符夫人使用
1) “.”操作符
使用“.”操作符,可以访问上面所述的EL隐含对象的值。
“.”操作符的语法:
- 左边是Map 或 Bean
- 右边必须是一个Map的key或一个bean的property名,右边必须遵循Java命名规则。

2)[ ]操作符
“[ ]”操作符的语法:
- 左边是Map 或 Bean 或 List 或 数组
- 右边除了和 “.”操作符一样,还可以是数字、能转换成数字的其他类型。

总结
对于Bean和Map,“.”和“[ ]”操作符可以互换。如果[ ]中不是字符串,表达式将被看作求值。
例如下面这个例子,Music is ${musicMap[Genre]}里的Genre不是字符串,就被看作是map对象的求值,转化为箭头右边的形式。

3)在括号中使用嵌套表达式

3. EL隐含对象的应用
1)PageContext对象的应用
PageContext隐含对象用于访问JSP内置对象,如request、response、out、session、config和servletContext等,例如要访问当前session中的变量username可以使用如下的表达式
1 | ${PageContext.session.username} |
2)param和paramValues对象的应用
param对象用于获取请求参数的值。而如果一个参数名对应多个值时,则需要使用paramValues对象获取请求参数的值,在应用param对象时,返回的结果是字符串。应用paramValues对象时,返回的结果是数组。
例如:在JSP页面中有一个名为user的文本框,关键代码如下
1 | <input type = "text" name = "user" id = "user"> |
当表单提交之后,要获取user文本框的值,通过
1 | ${param.user} |
例如:当JSP页面有名为color的复选框
1 | <input type = "checkbox" name = "color" value = "1" id = "hobby">red |
当表单提交之后,要获取color的值,通过
1 | ${paramValues.color[0]}//red |
下面是一个简易的例子,用户在客户端输入数据,在jsp页面通过el表达式获取数据。

3)cookie对象的应用
cookie对象用于访问由请求设置的cookie名称,如果在cookie中已经设定了一个名为username的值,那么可以使用${cookie.username}来获取cookie对象;但是如果要获取cookie中的值,则需要使用cookie对象的value属性。
例如:使用response对象设置一个请求有效的cookie对象,然后使用EL表达式获取该cookie对象的值
1 | <% Cookie cookie = new Cookie("user","zhang") |
4)获取上下文初试参数
在DD中配置上下文初始参数,可以通过initParam获取参数值

2.3 include标准动作
都我们需要重复一段代码(比如页面头部)的时候,我们想到之前学的Include指令
1 | <%@ include file= "header.jsp"%> |
现在介绍一种新的方法——Include标准动作
1 | <jsp:include page="header.jsp"/> |
两种方法效果完全相同,但是底层实现却完全不同。
- Include指令在转换JSP页面时将header.jsp源码插入,也就是把header.jsp的内容插入到原来jsp文件,在转化为servlet的java源文件。
- Include标准动作在运行时将header.jsp的响应插入到原jsp的响应中。
1)Include标准动作
如上面所见jsp:include可以在页面被请求的时候引入另一个文件,那么在源页面和嵌入的页面之间是否可以传递请求参数呢?比如我们希望每个人登录进系统后,页面头部显示用户的昵称等信息。
<jsp:include>
标签可以有内容,通过使用<jsp:param>
可以定制嵌入的页面的内容。
例如下面这个例子
主页面:
1 | <html><body> |
嵌入的文件
1 | <img src="/logo.png"><br> |
2) forward标准动作
forward标准动是把请求转到一个新的页面。
<jsp:forward page=“target.jsp” />的作用就相当于RequestDispatcher。