JSP
JSP
JSP:Java Server Pages,一种动态web资源的开发技术
API文档
调用和运行原理
JSP的工作模式是请求/响应模式,客户端首先发出HTTP请求,JSP程序收到请求后进行处理并返回处理结果。在一个JSP文件第一次被请求时,JSP引擎(容器)把该JSP文件转换成为一个Servlet,而这个引擎本身也是一个Servlet。
JSP的运行过程具体如下:
客户端发出请求,请求访问JSP文件。
JSP容器先将JSP文件转换成一个Java源文件(Java Servlet源程序),在转换过程中,如果发现JSP文件中存在任何语法错误,则中断转换过程,并向服务端和客户端返回出错信息。
如果转换成功,则JSP容器将生成的Java源文件编译成相应的字节码文件*.class。该class文件就是一个Servlet,Servlet容器会像处理其他Servlet一样来处理它。
注意:若是文件中存在JSTL或者EL表达式的话,那么在何时解析这些变量呢?答案是在将JSP文件解析成对应的Java源文件的时候就对JSTL或者EL表达式进行解析了,也就是说,当从服务器往浏览器写出页面内容时,JSTL或者EL中的变量就已经被解析成具体的值了。
JSP本质是一个servlet.
每个JSP页面在第一次被访问时,WEB容器会把请求交给JSP引擎(即一个JAVA程序)处理。JSP引擎先将JSP翻译成一个_jspServlet
(实质也是一个servlet),然后按照servlet的调用方式进行调用。
- 服务器会将jsp先翻译成servlet,这个servlet位于tomcat服务器
work
目录,这jsp类的父类是org.apache.jasper.runtime.HttpJspBase
,这个HttpJspBase
类继承自HttpServlet
- 向服务器发请求会调用servlet的service方法;同样地,访问jsp会调用这个JSP类的
_jspService
方法。 - JSP中的标签语言会在
_jspService
方法中通过out.write()
写出来;JSP中的Java代码会原封不动的搬到_jspService
方法中。 - 在
_jspService
方法中提前准备好了一些对象供JSP调用,如:out,page,application,request,response
等等。 - 由于第一次访问时会翻译成servlet,所以第一次访问较慢。
下面以demo1.jsp
为例,展示对应的类%CATALINA_HOME%\work\Catalina\localhost\hello\org\apache\jsp\demo1_jsp.java
中的部分代码
示例1:demo1.jsp
<%@ page import="java.util.Date" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2016/1/27
Time: 16:45
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>demo1</title>
</head>
<body>
当前时间时:
<%
Date date = new Date();
out.write(date.toGMTString());
%>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
示例2:_jspService
方法中代码片段
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>demo1</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("当前时间时:\r\n");
Date date = new Date();
out.write(date.toGMTString());
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
示例3:_jspService
方法中一些定义的对象
final javax.servlet.jsp.PageContext pageContext;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
2
3
4
5
6
7
JSP语法
JSP 声明
<%! declaration; [ declaration; ]+ ... %>
下面是简单的例子JSP声明:
<%! int i = 0; %>
<%! int a, b, c; %>
<%! Circle a = new Circle(2.0); %>
2
3
JSP表达式
JSP表达式元素包含计算,转换为字符串,并插入出现在JSP文件的脚本语言表达式。
因为一个表达式的值被转换为字符串,可以在文本一行内使用表达式,不管它是否被标记使用在HTML,JSP文件中。
表达元素可以包含任何Java语言规范有效的表达式,但是不能使用一个分号来结束表达式。
下面是JSP表达式的语法:
<%= expression %>
下面是简单的例子JSP表达式:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP表达式 </title>
</head>
<body>
<p>
今天是:<%=(new java.util.Date()).toLocaleString()%>
</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
表达式脚本的特点:
1、所有的表达式脚本都会被翻译到_jspService()
方法中
2、表达式脚本都会被翻译成为out.print()
输出到页面上
3、由于表达式脚本翻译的内容都在_jspService()
方法中,所以_jspService()
方法中的对象都可以直接使用。
4、表达式脚本中的表达式不能以分号结束。
JSP注释
JSP注释标记的文字或语句都会被JSP容器忽略。当想要隐藏或“注释掉”JSP页面的一部分,JSP注释是很有用的。
以下是JSP注释语法:
<%-- This is JSP comment --%>
JSP注释示例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>注释 - 示例</title></head>
<body>
<h2>A Test of Comments</h2>
<%-- This comment will not be visible in the page source --%>
</body>
</html>
2
3
4
5
6
7
8
还有少数特殊的结构可以使用一些情况,插入注释或字符,将被特殊处理。这里有一个整理汇总:
语法 | 目的 |
---|---|
<%-- comment --%> | JSP注释,它将被JSP引擎忽略 |
<!-- comment --> | HTML注释,它将被浏览器忽略 |
<% | 表示静态<%的字面量 |
%> | 表示静态%>的字面量 |
\' | 在使用单引号在属性中的单引号 |
\ " | 双引号在属性使用双引号 |
JSP 指令
JSP指令影响的servlet类的整体结构。它通常有以下形式:
<%@ directive attribute="value" %>
有三种类型的指令标记:
指令 | 描述 |
---|---|
<%@ page ... %> | 定义页面依赖属性,例如脚本语言,错误页面和缓冲的要求 |
<%@ include ... %> | 包括在转换阶段的文件 |
<%@ taglib ... %> | 声明了一个标签库,包含自定义动作,用在页面中 |
page指令语法:
<%@ page
[ language="java" ]
[ extends="package.class" ]
[ import="{package.class | package.*}, ..." ]
[ session="true | false" ]
[ buffer="none | 8kb | sizekb" ]
[ autoFlush="true | false" ]
[ isThreadSafe="true | false" ]
[ info="text" ]
[ errorPage="relativeURL" ]
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]
[ isErrorPage="true | false" ]
%>
2
3
4
5
6
7
8
9
10
11
12
13
errorPage
:错误提示页面。也可在web.xml
的<error-page>
标签配置,异常处理页面。在page指令设置的优先级高于在web.xml
配置。pageEncoding
:JSP引擎以何种码表翻译JSP,该值需和JSP文件的保存编码一致,且若要在浏览器正确显示,还要和contentType
一致。contentType
: 表示jsp 返回的数据类型是什么。也是源码中response.setContentType()参数值autoFlush
: 属性设置当out 输出流缓冲区满了之后,是否自动刷新冲级区。默认值是truebuffer
属性设置out 缓冲区的大小。默认是8kbisErrorPage
属性设置当前jsp 页面是否是错误信息页面。默认是false。如果是true 可以获取异常信息session
属性设置访问当前jsp 页面,是否会创建HttpSession 对象。默认是trueextends
属性设置jsp 翻译出来的java 类默认继承谁。
JSP 动作
JSP动作使用XML语法结构来控制Servlet引擎的行为。可以动态地插入文件,重用JavaBeans组件,用户转发到另一个页面,或为Java插件生成HTML。
只有一个用于动作元素的语法,因为它符合XML标准:
<jsp:action_name attribute="value" />
动作元素基本上都是预先定义函数并有以下可用的JSP操作:
语法 | 目的 |
---|---|
jsp:include | 包括页面被一次请求的文件 |
jsp:useBean | 查找或实例化一个JavaBean |
jsp:setProperty | 设置一个JavaBean 的属性 |
jsp:getProperty | 插入一个JavaBean 的属性到输出 |
jsp:forward | 转发请求到一个新的页面 |
jsp:plugin | 生成特定浏览器的代码,使对象或嵌入标签Java插件 |
jsp:element | 定义XML元素动态 |
jsp:attribute | 定义动态定义XML元素的属性 |
jsp:body | 定义动态定义的XML元素主体 |
jsp:text | 用于编写模板文本在JSP页面和文档 |
JSP 九大内置对象
名称 | 类型 | 描述 |
---|---|---|
out | javax.servlet.jsp.JspWriter | 这是用于将输出发送给客户端的PrintWriter对象 |
request | javax.servlet.http.HttpServletReqeust | 这是与请求相关联的HttpServletRequest对象 |
response | javax.servlet.http.HttpServletResponse | 这是用于响应客户端相关联的HttpServletResponse对象 |
config | javax.servlet.ServletConfig | 这是与页面关联的ServletConfig对象 |
session | javax.servlet.http.HttpSession | 这是与请求相关联的HttpSession对象 |
application | jaax.servlet.ServletContext | 这是应用程序上下文关联的ServletContext对象 |
page | java.lang.Object | 这是一个简单的代名词,是用来调用由转换servlet类中定义的方法 |
exception | java.lang.Throwable | Exception 对象允许例外的数据由JSP指定访问 |
pageContext | javax.servlet.jsp.PageContext | 这封装采用类似更高的性能JspWriters服务器特定的功能 |
out隐式对象
out隐式对象:用于向客户端发送文本数据。通过调用pageContext
对象的getOut
方法返回,类型为JspWriter
,作用和ServletResponse.getWriter
返回的PrintWriter
对象相似。
JspWriter
相当于自带缓存功能的PrintWriter
,设置page指令的buffer属性课调整缓存大小。满足如下条件之一,out对象才调用ServletResponse.getWriter
方法,并通过返回的PrintWriter
对象将out对象的缓冲区的内容真正写入到servlet引擎提供的缓冲区中:
- 设置page指令的buffer属性关闭的out对象的缓存功能
- out对象的缓冲区已满
- 整个JSP页面结束
例子:
<%
out.write("out.write<br/>");
response.getWriter().write("response.getWriter.write<br/>");
%>
2
3
4
浏览器显示:
response.getWriter.write
out.write
2
可见,由于out有缓冲,所以后显示。
pageContext对象
pageContext对象:是JSP技术中最重要的一个对象,它代表JSP页面的运行环境
- 封装了对其他8大隐式对象的引用(主要用于自定义标签开发)
- 自身是一个域对象,可用来保存数据(page域存的东西只能在页面范围内拿得出来)
- 封装了web开发中的一些常用操作(提供管理所有域的入口),如:引入和跳转其他资源、检索其他域对象中的属性等
Class PageContext的API文档
四大域对象
pageContext: (PageContextImpl 类) 当前jsp 页面范围内有效
Request 范围: (HttpServletRequest 类) 使用该JSP对象可以在请求服务任何地方使用(一次请求内有效)。
Session 范围: (HttpSession 类) 使用该JSP的对象可用于在属于同一个会话页面(一个会话范围内有效【打开浏览器访问服务器,直到关闭浏览器】)。
Application 范围: (ServletContext 类) 使用该JSP的对象可以在整个应用程序页面中使用(整个web 工程范围内都有效【只要web 工程不停止,数据都在】)。
四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序。
pageContext =>>> request =>>> session =>>> application
将下面的代码编写到 scope1.jsp 文件,代码内容如下所示:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="Pag" value="Page Value" scope="page" />
<c:set var="Req" value="Request Value" scope="request" />
<c:set var="Ses" value="Session Value" scope="session" />
<c:set var="App" value="Application Value" scope="application" />
<html>
<body>
<h2>JSP对象范围示例一:</h2>
<b>Page Scope</b> ::<c:out value="${Pag}" /><br>
<b>Request Scope</b> ::<c:out value="${Req}" /><br>
<b>Session Scope</b> ::<c:out value="${Ses}" /><br>
<b>Application Scope</b>::<c:out value="${App}" /><br>
<a href="scope2.jsp">下一页Session,Application范围</a>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Page 范围:
使用此JSP对象可以在其中创建的页面内使用。
JSP代码脚本
<%
java语句
%>
2
3
代码脚本的特点是:
1、代码脚本翻译之后都在_jspService
方法中
2、代码脚本由于翻译到_jspService()
方法中,所以在_jspService()
方法中的现有对象都可以直接使用。
3、还可以由多个代码脚本块组合完成一个完整的java 语句。
4、代码脚本还可以和表达式脚本一起组合使用,在jsp 页面上输出数据
控制流语句
JSP提供了Java的全部功能可以嵌入在Web应用程序。可以使用Java的所有API和构建块在JSP编程,包括决策语句,循环等。
决策声明
在if ... else
块开头时就像一个普通的Scriptlet,但 Scriptlet 每一行是封闭的,包括scriptlet标记之间的HTML文本。创建一个JSP文件为:if-else.jsp
,并写入以下代码:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%! int day = 3; %>
<html>
<head><title>IF...ELSE 示例</title></head>
<body>
<% if (day == 1 | day == 7) { %>
<p> Today is weekend</p>
<% } else { %>
<p> Today is not weekend</p>
<% } %>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
switch...case
块,编写通过使用out.println()
和内小脚本有一点不同,把下面代码保存到switch-case.jsp
文件中,代码详细如下:
<%! int day = 3; %>
<html>
<head><title>SWITCH...CASE 示例</title></head>
<body>
<%
switch(day) {
case 0:
out.println("It\'s Sunday.");
break;
case 1:
out.println("It\'s Monday.");
break;
case 2:
out.println("It\'s Tuesday.");
break;
case 3:
out.println("It\'s Wednesday.");
break;
case 4:
out.println("It\'s Thursday.");
break;
case 5:
out.println("It\'s Friday.");
break;
default:
out.println("It's Saturday.");
}
%>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
循环语句
还可以使用在Java中三种基本循环类型块:for
, while
,and do.while
块在JSP编程中。
让我们来看看下面的for
循环示例,把下面代码保存到 loop-for.jsp 文件中,代码详细如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%! int fontSize; %>
<html>
<head><title>FOR 循环示例</title></head>
<body>
<%for ( fontSize = 1; fontSize <= 3; fontSize++){ %>
<font color="green" size="<%= fontSize %>">
JSP Tutorial
</font><br />
<%}%>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
while
循环编写,把下面代码保存到 loop-while.jsp 文件中,代码详细如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%! int fontSize; %>
<html>
<head><title>WHILE循环示例</title></head>
<body>
<h2>While循环示例:</h2>
<%while ( fontSize <= 5){ %>
<font color="green" size="<%= fontSize %>">
JSP Tutorial
</font><br />
<%fontSize++;%>
<%}%>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
在JSP页面中创建方法
方法即是可以在一个JSP页面被用于执行特定操作的一个代码段。
创建一个方法示例:
<%!
public int mul(int a, int b){
return a * b;
}
%>
2
3
4
5
两个数相乘的结果是:<%= mul(2, 2) %>
以上代码保存,并执行结果如下:
两个数相乘的结果是:4
另外,在上述例子中使用的方法是:mul,将返回一个整数值作为输出。 它需要两个整数“a”,“b”作为参数,以产生两个数字的乘积作为输出。
在JSP页面中使用数组
由于JSP不是一个完整的编程语言不具有数组的声明,但使用Java中的数据结构在JSP中使用是完全没有问题的。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String[] arr={"apple","orange","cherry"};
%>
<%
int j;
out.println("<p>数组中所有元素是:</p>");
for(j=0;j<arr.length;j++){
out.println(arr[j]);
}
%>
2
3
4
5
6
7
8
9
10
11
在JSP中使用Java Bean
Java bean只不过是一个实现java.io.Serializable
接口,并且使用set/get
方法来投射类的属性。因为它们是一个Java bean类的实例并可重复使用,在JSP页面中提供了灵活性,。
嵌入一个Java bean到JSP网页,有三个基本动作或标签:<jsp:useBean>
, <jsp:setProperty>
, <jsp:getProperty>
jsp:useBean 这个标签是用来给bean指定“id”和“scope”属性相关联。
jsp:setProperty 这个标签被用于设置一个beans属性的值,主要使用“name”属性已经定义了相同的范围对象。其他属性是 "property", "param", "value"
jsp:getProperty 这个标签是用来获取引用Bean实例属性并将其存储到隐式out对象。
Beans的规则:
- 包应该是java bean的第一行
- Bean应该有一个空的构造
- 所有的bean中的变量应该设置有“get”,“set”方法。
- 属性名应以大写字母开头在使用“set”,“get”方法时。
- 例如变量“名称”的get,set方法就是getName(), setName(String)
- 设置方法应该返回像一个空(void)值: "return void()"
jsp与JavaBean
JavaBean是一个遵循特定写法的java类,JavaBean常用于封装数据,具有如下热点:
- 该java类必须有一个无参的构造函数
- 属性必须私有化
- 私有化的属性必须通过public类型的方法暴露给其他程序,并且方法的命名也必须遵循一定的命名规范。
JSP中提供了三个关于JavaBean的标签:
<jsp:useBean>
:用于在JSP页面中查找或实例化一个JavaBean组件<jsp:setProperty>
:用于在JSP页面中设置一个JavaBean组件的属性<jsp:getProperty>
:用于在JSP页面中获取一个JavaBean组件的属性
一些细节
<jsp:useBean>
标签的标签体只在实例化bean时才执行<jsp:setProperty>
可用请求参数给bean属性赋值,支持8种基本数据类型的转换(把客户机提交的字符串转成相应的8种基本类型赋到bean的属性上)- 在标签中将
property="*"
,用所有请求参数为bean赋值,请求参数名称和bean属性名称必须要一致 - 如果JavaBean实例对象的某个属性值为null,那么使用
<jsp:getProperty>
标签输出结果为**"null"字符串**
bean.java
package bean;
public class Counter
{
int count = 0;
String name;
public Counter() { }
public int getCount()
{
return this.count;
}
public void setCount(int count){
this.count = count;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name=name;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use-bean.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page language="java" %>
<%@ page import="bean.Counter" %>
</body>
<jsp:useBean id="counter" scope="page" class="bean.Counter" />
<jsp:setProperty name="counter" property="count" value="4" />
Get Value: <jsp:getProperty name="counter" property="count" /><BR>
<jsp:setProperty name="counter" property="name" value="baidu.com" />
Get Name: <jsp:getProperty name="counter" property="name" /><BR>
2
3
4
5
6
7
8
9
使用<jsp:useBean>
动作包含bean.Counter
这个bean
,并设置此bean
的id
为counter
,范围是page
.使用<jsp:setProperty>
设置id=counter
的bean
的count
属性 的值为 4
,以及设置name
的值为 baidu.com.
并使用 <jsp:getProperty>
来获取它们的值。
JSP 运算符
JSP支持所有支持Java的逻辑和算术运算符。下表给出了所有的运算符,具有最高优先级将排在表的顶部, 运算级别最低的放在底部。
在一个表达式中,具有更高的优先级运算符将首先计算评估。
分类 | 操作符 | 关联 |
---|---|---|
后缀 | () [] . (点运算符) | 左->右 |
一元 | ++ - - ! ~ | 右->左 |
乘法 | * / % | 左->右 |
加法 | + - | 左->右 |
位移 | >> >>> << | 左->右 |
关系 | > >= < <= | 左->右 |
相等 | == != | 左->右 |
位与/AND | & | 左->右 |
位XOR | ^ | 左->右 |
位OR | | | 左->右 |
逻辑AND | && | 左->右 |
逻辑OR | | | | 左->右 |
关系 | ?: | 右->左 |
赋值 | = += -= *= /= %= >>= <<= &= ^= |= | 右->左 |
逗号 | , | 左->右 |
JSP 字面量
JSP表达式语言定义了以下字面量:
- Boolean: true 或 false
- Integer: 与Java中的一样
- Float: 与Java中的一样
- String: 单引号和双引号; " 转义为 "。' 转义为 ', 以及 \ 转义为 \
- Null: null
JSP Session
会话处理变得必不可少,当一个请求数据需要被持续保持以供进一步使用。 由于HTTP协议认为每个请求是一个新的请求,它不能保持过去访问的数据,因此会话处理就变得很重要。以下是一些来处理会话的方法。
- JSP中每当发起一个请求,服务器产生一个存储在客户机的唯一会话ID。
- Cookies存储信息在客户端浏览器
- URL重写会话信息附加到URL的末尾
- 隐藏的表单域将SessionID嵌入到GET和POST命令。
创建一个页面 session.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Session示例</title></head>
<body>
<h2>Session示例:</h2>
<form method = "post" action="session2.jsp">
<font>Username<input type = "text" name = "name"></font>
</font><br><br>
<input type = "submit" name = "submit" value = "提交" >
</form>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
创建另一个页面 session2.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Session示例2</title></head>
<body>
<%
String name = request.getParameter("name");
if((name!=null))
{
session.setAttribute("username",name);
}
%>
<a href="session3.jsp">继续,跳转到session3.jsp</a>
2
3
4
5
6
7
8
9
10
11
12
13
14
创建另一个页面 session3.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Session示例3</title></head>
<body>
<font>欢迎您,</font> <%= session.getAttribute("username") %>
</body>
</html>
2
3
4
5
6
7
在第一个示例中的 "session1.jsp" 是用来提供一个表单以获得用户名。 当提交表单时它转到第二个文件session2.jsp,它调用表单的“action”属性。一个Session的属性使用 "session.setAttribute"设置在这里. 在第三个文件 "session3.jsp" 相同的值使用"session.getAttribute" 来显示出来。
JSP Cookies信息处理
Cookies
和会话有一些相似的地方,唯一的区别是cookies
存储在浏览器。而会话存储在服务器端。让我们来看看在JSP中处理Cookies
的一些例子:
示例代码: cookie1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<body>
<form method = "post" action="cookie2.jsp">
<font>Username<input type = "text" name = "name"></font>
</font><br>
<input type = "submit" name = "submit" value = "submit" >
</form>
</body>
</html>
2
3
4
5
6
7
8
9
10
示例代码: cookie2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page language="java" import="java.util.*"%>
<%
String name=request.getParameter("name");
Cookie cookie = new Cookie ("name",name);
response.addCookie(cookie);
cookie.setMaxAge(50 * 50); //Time is in Minutes
%>
<a href="cookie3.jsp">Continue</a>
2
3
4
5
6
7
8
9
示例代码: cookie3.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<p>显示Cookie的值:</p>
<%
Cookie[] cookies = request.getCookies();
for (int i=0; i<cookies.length; i++){
if(cookies[i].getName().equals("name"))
out.println("Hello"+cookies[i].getValue());
}
%>
2
3
4
5
6
7
8
9
在第一个例子cookie1.jsp
中,使用表单得到用户名。当表单提交进入第二页cookie2.jsp
其中Cookie使用cookie.setMaxAge
函数设置过期时间。在第三个页面cookie3.jsp
中,cookie
使用函数request.getCookies()
,并使用循环是得到了字段username
的值并显示。
删除Cookies
示例代码: cookie4.jsp
<%
Cookie cookie = new Cookie( "name", "" );
cookie.setMaxAge( 0 );
%>
2
3
4
另外,在上述例子中,我们已经创建的 cookie
的新实例并使用一个null
值并将cookie
的age
设定为0
。 这将删除cookie
。
- JSP模板元素:JSP页面中的HTML内容。定义了网页的基本骨架,即结构和外观。
- JSP表达式:用于将程序数据输出到客户端。如,
<%=变量或表达式 %>
脚本表达式(无分号),用于输出数据。 - JSP脚本片段:用于在JSP页面中编写多行java代码,严格遵循java语法。一个JSP页面可有多个脚本片段,它们可以相互访问(和放在一对
<% %>
中一样),单个片段可不完整。- <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
- <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
- <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
- JSP声明:JSP中代码默认翻译到servlet的service方法中,而JSP声明中的代码被翻译到
_jspService
方法外。语法:<%! java代码 %>
。 - JSP注释:格式
<%-- 注释 --%>
,注释的内容不会发给浏览器。 - JSP指令:是为JSP引擎设计的,定义了三个指令:page指令,include指令,taglib指令。语法:
<%@ 指令 属性名="值" %>
。- page指令:定义各种属性,作用于整个JSP页面。
- include指令:用于包含JSP文件(页头、页脚)。属于静态包含(编译时包含),它包含的所有JSP会编译成一个servlet。
- taglib指令:用于在JSP页面导入标签库。
- JSP标签:也称为jsp Action元素,用于在jsp页面中提供业务逻辑功能,避免在jsp页面中直接写java代码而难以维护
- JSP内置对象:九大隐式对象,
request,response,session,application,config,page,exception,out,pageContext
jsp映射和查错
jsp映射
在webxml
的<servlet>
标签中加<jsp-file>
标签,其他的和servlet映射一样
查找jsp页面中的错误
- JSP页面中的语法格式有问题,导致不能翻译成servlet源文件,JSP引擎将提示这类错误在JSP页面中的位置以及相关信息
- JSP页面中的语法格式没有问题,但翻译承德servlet源文件出现java语法问题导致源文件编译不通过,JSP引擎将提示这类错误在JSP页面中的位置以及相关信息
- JSP页面翻译成的servlet程序运行时出现异常,这和普通java程序运行时错误完全一样,java虚拟机将提示错误在servlet源文件中的位置以及相关信息
jsp 中的out 输出和response.getWriter 输出的区别
- response 中表示响应,我们经常用于设置返回给客户端的内容(输出)
- out 也是给用户做输出使用的。
由于jsp 翻译之后,底层源代码都是使用out 来进行输出,所以一般情况下。我们在jsp 页面中统一使用out 来进行输出。避
免打乱页面输出内容的顺序。
- out.write() 输出字符串没有问题
- out.print() 输出任意数据都没有问题(都转换成为字符串后调用的write 输出)
- 深入源码,浅出结论:在jsp 页面中,可以统一使用out.print()来进行输出
JSP常用标签
jsp 静态包含
示例说明:
<%--
<%@ include file=""%> 就是静态包含
file 属性指定你要包含的jsp 页面的路径
地址中第一个斜杠/ 表示为http://ip:port/工程路径/ 映射到代码的web 目录
静态包含的特点:
1、静态包含不会翻译被包含的jsp 页面。
2、静态包含其实是把被包含的jsp 页面的代码拷贝到包含的位置执行输出。
--%>
<%@ include file="/include/footer.jsp"%>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jsp 动态包含
<%--
<jsp:include page=""></jsp:include> 这是动态包含
page 属性是指定你要包含的jsp 页面的路径
动态包含也可以像静态包含一样。把被包含的内容执行输出到包含位置
动态包含的特点:
1、动态包含会把包含的jsp 页面也翻译成为java 代码
2、动态包含底层代码使用如下代码去调用被包含的jsp 页面执行输出。
JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
3、动态包含,还可以传递参数
--%>
<jsp:include page="/include/footer.jsp">
<jsp:param name="username" value="bbj"/>
<jsp:param name="password" value="root"/>
</jsp:include>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
动态包含的底层原理
JSP标签-转发
<%--
<jsp:forward page=""></jsp:forward> 是请求转发标签,它的功能就是请求转发
page 属性设置请求转发的路径
--%>
<jsp:forward page="/scope2.jsp"></jsp:forward>
2
3
4
5
EL表达式
一般的都是先将数据存储到Session,request,ServletContext等域对象中,再利用EL表达式来获取。
- 语法
- 以"${"符号开始,以"}"符号结束,具体格式:
${表达式}
。
- 以"${"符号开始,以"}"符号结束,具体格式:
- 获取数据
- 类似page.findAttribute(); 先从page域中查找,没有找到去request域中查询,没找到去session域中找,没找到就去application域中找。
- 注意:1. 在用EL表达式获取数据时,必须保证该数据存在于四个域对象其中的一个。 2. 在获取数据时,一定不要忘记加${}。
JSTL表达式
- 使用时务必注意不要忘记导入JSTL的jar包:
jstl.jar
和standard.jar
。 - 要使用taglib指令导入Core标签库:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
。
c:forEach标签
- 语法
<c:forEach [var="varName" items="collection" [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
${varName}
</c:forEach>
2
3
参数解释
- var属性用于指将当前迭代到的元素保存到page域中的名称
- items属性用于指定将要迭代的集合对象
- varStatus用于指定当前迭代状态信息的对象保存到page域中的名称
- begin属性用于指定从集合中第几个元素开始迭代,begin的索引值从0开始,如果没有指定items属性,就从begin指定的值开始迭代,知道迭代结束为止
- step属性用于指定迭代的步长,即迭代因子的增量
实例
<c:forEach items="${userMap}" var="entry"> ${entry.key}====${entry.value} </c:forEach>
1
2
3注意:items里面需要使用到EL表达式的时候,一定不要忘记加${}
在页面中使用JSTL需要在jsp中 通过指令进行设置
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
prefix="c"
表示后续的标签使用都会以<c:
开头
<c:set var="name" value="${'gareen'}" scope="request" />
通过标签获取name: <c:out value="${name}" /> <br>
<c:remove var="name" scope="request" /> <br>
通过标签获取name: <c:out value="${name}" /> <br>
2
3
4
5
6
7
判断语句
JSTL通过<c:if test="">
进行条件判断
但是JSTL没有<c:else
,所以常用的办法是在<c:if
的条件里取反
配合if
使用的还有通过empty
进行为空判断
empty
可以判断对象是否为null
,字符串长度是否为0
,集合长度是否为0
<c:set var="hp" value="${10}" scope="request"/>
<c:if test="${hp<5}">
<p>这个英雄要挂了</p>
</c:if>
<c:if test="${!(hp<5)}">
<p>这个英雄觉得自己还有救</p>
</c:if>
<c:set var="weapon" value="${null}" scope="page"/>
<c:set var="lastwords" value="${''}" scope="page"/>
<%
List lis = new ArrayList();
%>
<c:set var="items" value="${list}" scope="page"/>
<c:if test="${empty weapon}">
<p>没有武器了</p>
</c:if>
<c:if test="${empty lastwords}">
<p>挂了也没有遗言</p>
</c:if>
<c:if test="${empty items}">
<p>物品栏为空</p>
</c:if>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
choose语句
<c:choose>
<c:when test="${hp1<5}">
<p>这个英雄觉得自己要挂了</p>
</c:when>
<c:otherwise>
<p>这个英雄觉得自己还可以再抢救抢救</p>
</c:otherwise>
</c:choose>
2
3
4
5
6
7
8
forEach
items="${heros}"
表示遍历的集合
var="hero"
表示把每一个集合中的元素放在hero上
varStatus="st"
表示遍历的状态
<%
List<String> heros = new ArrayList<String>();
heros.add("塔姆");
heros.add("艾克");
heros.add("巴德");
heros.add("雷克赛");
heros.add("卡莉丝塔");
request.setAttribute("heros",heros);
%>
<table width="200px" align="center" border="1" cellspacing="0">
<tr>
<td>编号</td>
<td>英雄</td>
</tr>
<c:forEach var="hero" items="${heros}" varStatus="st">
<tr>
<td><c:out value="${st.count}"/> </td>
<td><c:out value="${hero}"/> </td>
</tr>
</c:forEach>
</table>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
forToken
<c:forTokens
专门用于字符串拆分,并且可以指定多个分隔符
<c:set var="heros" value="塔姆,艾克;巴德|雷克赛!卡莉丝塔" />
<c:forTokens items="${heros}" delims=":;|;!" var="hero">
<c:out value="${hero}"/><br/>
</c:forTokens>
2
3
4
fmt:formatNumber 格式化数字
fmt 标签常用来进行格式化,其中fmt:formatNumber用于格式化数字 使用之前要加上
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix='fmt' %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix='fmt' %>
<c:set var="moeny" value="888.8888"/>
<c:set var="pi" value="3.1415926"/>
<fmt:formatNumber type="number" value="${moeny}" minFractionDigits="2"/><br/>
<fmt:formatNumber type="number" value="${pi}" maxFractionDigits="2"/><br/>
2
3
4
5
<fmt:formatNumber
表示格式化数字
minFractionDigits
小数点至少要有的位数
maxFractionDigits
小数点最多能有的位数
fmt:formatDate 格式化日期
<fmt:formatDate
表示格式化日期
yyyy
表示年份
MM
表示月份
dd
表示日期
E
表示星期几
a
表示是上午还是下午
HH
表示小时
mm
表示分钟
ss
表示秒
S
表示毫秒
z
表示时区
<%
Date now = new Date();
pageContext.setAttribute("now",now);
%>
完整日期: <fmt:formatDate value="${now}" pattern="G yyyy年MM月dd日 E"/><br>
完整时间: <fmt:formatDate value="${now}" pattern="a HH:mm:ss.S z"/><br>
常见格式: <fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss"/>
2
3
4
5
6
7
8
fn:
fn标签提供各种实用功能,首先使用之前使用加入如下指令
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
用法举例:
${fn:substring(name, 0, 5)}
函数 | 描述 |
---|---|
fn:contains(string, substring) | 如果参数string中包含参数substring,返回true |
fn:containsIgnoreCase(string, substring) | 如果参数string中包含参数substring(忽略大小写),返回true |
fn:endsWith(string, suffix) | 如果参数 string 以参数suffix结尾,返回true |
fn:escapeXml(string) | 将有特殊意义的XML (和HTML)转换为对应的XML character entity code,并返回 |
fn:indexOf(string, substring) | 返回参数substring在参数string中第一次出现的位置 |
fn:join(array, separator) | 将一个给定的数组array用给定的间隔符separator串在一起,组成一个新的字符串并返回。 |
fn:length(item) | 返回参数item中包含元素的数量。参数Item类型是数组、collection或者String。如果是String类型,返回值是String中的字符数。 |
fn:replace(string, before, after) | 返回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方,并返回替换后的结果 |
fn:split(string, separator) | 返回一个数组,以参数separator 为分割符分割参数string,分割后的每一部分就是数组的一个元素 |
fn:startsWith(string, prefix) | 如果参数string以参数prefix开头,返回true |
fn:substring(string, begin, end) | 返回参数string部分字符串, 从参数begin开始到参数end位置,包括end位置的字符 |
fn:substringAfter(string, substring) | 返回参数substring在参数string中后面的那一部分字符串 |
fn:substringBefore(string, substring) | 返回参数substring在参数string中前面的那一部分字符串 |
fn:toLowerCase(string) | 将参数string所有的字符变为小写,并将其返回 |
fn:toUpperCase(string) | 将参数string所有的字符变为大写,并将其返回 |
fn:trim(string) | 去除参数string 首尾的空格,并将其返回 |
JSP执行过程
以下是JSP遵循的过程
- 编译
- 初始化
- 执行
- 清理
JSP生命周期的四个主要阶段与Servlet生命周期非常相似。以下描述了四个阶段
1.JSP编译
当浏览器请求JSP时,JSP引擎首先检查是否需要编译页面。如果页面从未被编译,或者JSP从上一次编译以来JSP文件代码已被修改,那么JSP引擎将会编译页面。 编译过程包括三个步骤 -
- 解析JSP。
- 将JSP转换为servlet。
- 编译servlet。
2.JSP初始化
当容器加载JSP时,它会在处理任何请求之前调用jspInit()
方法。 如果需要执行特定于JSP的初始化,那么可以覆盖jspInit()
方法 -
public void jspInit(){
// Initialization code...
}
2
3
通常,初始化仅执行一次,并且与servlet的init()
方法一样,一般会在jspInit()
方法中初始化数据库连接,打开文件和创建查找表。
3.JSP执行
JSP生命周期的这个阶段表示所有与请求的交互,直到JSP被销毁为止。
每当浏览器请求JSP并且页面已被加载和初始化时,JSP引擎将调用JSP中的_jspService()
方法。
_jspService()
方法以HttpServletRequest
和HttpServletResponse
为参数,如下所示:
void _jspService(HttpServletRequest request, HttpServletResponse response) {
// Service handling code...
}
2
3
根据请求调用JSP的_jspService()
方法。它负责生成请求的响应,此方法还负责生成对所有七种HTTP方法的响应,即GET
,POST
,DELETE
等。
4.JSP清理
JSP生命周期的清理阶段表示当JSP被容器从使用中移除时。
jspDestroy()
方法是等效于servlet的destroy
方法的JSP方法。当需要执行清理工作时,可以覆盖jspDestroy()
方法,如:释放数据库连接或关闭打开的文件。
jspDestroy()
方法具有以下形式
public void jspDestroy() {
// Your cleanup code goes here.
}
2
3