一、JSP 结构
以下是表明Web服务器是如何使用JSP来创建网页的:
- 用户在浏览器上发送一个HTTP请求给服务器,web服务器会判断是否是JSP网页请求,如果是则启动JSP引擎。
- JSP引擎从磁盘中载入JSP文件,然后将它们翻译为servlet文件并将servlet编译成可执行类,再将原始请求传递给servlet引擎。这种转化只是简单地将所有模板文本改用println()语句,并且将所有的JSP元素转化成Java代码。
- web服务器的某组件将会调用servlet引擎,然后载入并执行servlet类。在执行过程中,servlet产生HTML格式的输出并将其内嵌于HTTP response中上交给Web服务器。
- web服务器以静态HTML网页的形式将HTTP response返回到您的浏览器中。
- 最后,web浏览器处理HTTP response中动态产生的HTML网页,就好像在处理静态网页一样。
二、JSP执行原理及本质
- 用户在浏览器地址栏上输入http://localhost:8080/hcz/index.jsp,web服务器判断用户请求的资源是hcz应用中index.jsp页面,web服务器在hcz应用中找到index.jsp
- 启动JSP引擎(是Tomcat服务器内置的一个JSP翻译引擎,专门负责翻译JSP文件,编译java源文件),将index.jsp翻译成index_jsp.java文件,并且将index_jsp.java文件编译生成index_jsp.class字节码文件,将其存储在Tomcat服务器work目录中。
- index_jsp.class类继承了HttpJspBase,HttpJspBase继承了HttpServlet,所以JSP本质上就是Servlet,和Servlet完全相同。
- 只有用户第一次访问这个JSP或者JSP页面被修改了,才会重新翻译。JSP有三个阶段:翻译(一次),编译(一次),运行(多次)。JSP更改,不需要重启服务器,也不需要重新部署项目。
- Jsp和Servlet本质上没有区别,但是JSP和Servlet它们的主要职责是有区别的:JSP主要是提取数据做页面展示,而Servlet主要完成业务逻辑处理以及资源跳转。Servlet是Controller(控制层),JSP是View(展示层)。
- 在JSP文件中编写的所有HTML、CSS、Javascript,对于JSP来说,只是普通的字符串,被翻译成:out.writer("…");
实例代码:执行JSP文件后翻译为Java文件的源代码是怎么样的?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<meta charset="UTF-8">
<title>jsp页面</title>
</head>
<body>
This is my JSP page. 666888<br>
账号:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="提交">
<%
System.out.println("666888");
%>
</body>
</html>
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" <meta charset=\"UTF-8\">\r\n");
out.write(" <title>jsp页面</title>\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write(" This is my JSP page. 666888<br>\r\n");
out.write(" 账号:<input type=\"text\" name=\"username\"><br>\r\n");
out.write(" 密码:<input type=\"text\" name=\"password\"><br>\r\n");
out.write(" <input type=\"submit\" value=\"提交\">\r\n");
out.write(" ");
System.out.println("666888");
out.write("\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
}
}
三、JSP生命周期
JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成servlet。
- 编译阶段:
当浏览器请求JSP页面时,JSP引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。
编译的过程包括三个步骤
- 解析JSP文件
- 将JSP文件转换为servlet
- 编译servlet
- 初始化阶段:
加载与JSP对应的servlet类,创建其实例,并调用它的初始化_jspInit()方法
public void _jspInit(){
// 初始化代码
}
一般来讲程序只初始化一次,servlet也是如此。通常情况下您可以在_jspInit()方法中初始化数据库连接、打开文件和创建查询表。
- 执行阶段:
这一阶段描述了JSP生命周期中一切与请求相关的交互行为,直到被销毁。
当JSP网页完成初始化后,JSP引擎将会调用_jspService()方法。
_jspService()方法需要一个HttpServletRequest对象和一个HttpServletResponse对象作为它的参数,就像下面这样:
public void _jspService(HttpServletRequest request,HttpServletResponse response)
{
// 服务端处理代码
}
- 销毁阶段:
调用与JSP对应的servlet实例的销毁方法_jspDestroy(),然后销毁servlet实例
public void jspDestroy()
{
// 清理代码
}
以上通过描述JSP的生命周期,发现和servlet生命周期非常相似,下面给出图示:
四、JSP语法
JSP文件以.jsp/.jspx结尾,通常存放在和HTML资源同级目录中,在JSP文件中编写的普通字符串,以后翻译成Servlet的service方法中的 out.write() 将该字符串响应给浏览器。所以我们必须在JSP文件中编写一些特殊的符号,和jsp文件中的普通文本加以区别,这样jsp引擎就会根据不能的符号将其翻译到Servlet类中的不同位置。
1. 脚本程序(scriptlet)
脚本程序的语法格式:
<% 代码片段 %>
- 在jsp文件中使用 <% %>,出现在该符号内的java程序翻译之后会被存放在Servlet的service方法中。
- 所以在该符号内只能编写java语句或者定义局部内部类(通常很少使用局部内部类),每一个java语句以 “;” 结尾,在这个符号中的程序大家就当做在service方法中编程一样就行了。
- 在该符号中声明的变量属于局部变量,不能使用访问控制权限修饰符修饰,所以在service方法中不能编写实例变量、不能编写方法、不能编写静态语句块。
<%-- 以下程序编译无法通过 --%>
<%--
public String username;
--%>
<%--
public void m1(){
}
--%>
<%--
static{
}
--%>
- 小脚本的数量随意,可以多个,小脚本中编写java程序出现在service方法中,service方法的代码是有执行顺序的,所以小脚本中的程序也是有顺序的。编写以下JSP文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
int i = 10;
%>
<html>
<%
System.out.println(i);
%>
<head>
<%
double d = 3.0;
%>
<meta charset="UTF-8">
<title>jsp页面</title>
<%
System.out.println(d + i);
%>
</head>
<body>
This is my JSP page<br>
<%
System.out.println(d*i);
%>
<%
out.println("Your IP address is " + request.getRemoteAddr());
%>
</body>
</html>
<%
String ename = "king";
System.out.println("ename = " + ename);
%>
其经过JSP引擎翻译后成Servlet的service方法变为:
public class index_jsp extends HttpJspBase{
public void _jspInit(){
}
public void _jspService(HttpServletRequest request,HttpServletResponse response){
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
int i = 10;
out.write("\r\n");
out.write("<html>\r\n");
out.write("\t");
System.out.println(i);
out.write("\r\n");
out.write(" <head>\r\n");
out.write(" \t");
double d = 3.0;
out.write("\r\n");
out.write(" <meta charset=\"UTF-8\">\r\n");
out.write(" <title>jsp页面</title>\r\n");
out.write(" ");
System.out.println(d + i);
out.write("\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write(" This is my JSP page<br>\r\n");
out.write(" \t ");
System.out.println(d*i);
out.write("\r\n");
out.write(" ");
out.println("Your IP address is " + request.getRemoteAddr());
out.write("\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
String ename = "king";
System.out.println("ename = " + ename);
}
}
2. JSP声明(declaration)
声明的语法格式:
<%! declaration; [ declaration; ]+ ... %>
- 在jsp文件中使用 <%! %> ,出现在该符号内的java程序翻译之后会被存放在和Servlet的service方法并列的位置上。
- 在该符号内声明静态变量、静态方法、静态代码块、实例代码块、实例变量、实例方法,大家就当做在类体中直接编码就可以了,所以声明的变量、方法都是可以使用访问控制权限修饰符修饰的。
- 声明块中不能直接编写java语句,除非是变量的声明。例如:
<%!
//java语句不能直接出现在类体中
//System.out.println("Hello World!");
public void doSome(){
System.out.println("do some!");
}
%>
实例代码:模拟JSP文件执行后在Servlet的service方法中的执行顺序是什么样的
<%@page contentType="text/html; charset=UTF-8"%>
<%
doSome();
%>
<%!
int i = 100;
%>
<%
//java语句不能直接出现在类体中
//System.out.println("Hello World!");
public void doSome(){
System.out.println("do some!");
}
%>
<%
System.out.println("servlet's service method execute!");
%>
<%!
static{
System.out.println("Class Loader!");
}
%>
<%
int j = 100;
%>
<%!
public static void doOther(){
System.out.println("do other!");
}
%>
<%
System.out.println("j = " + j);
System.out.println("i = " + i);
%>
其经过JSP引擎翻译后成Servlet的service方法变为:
public class index_jsp extends HttpJspBase{
int i = 100;
public void doSome(){
System.out.println("do some!");
}
static{
System.out.println("Class Loader!");
}
public static void doOther(){
System.out.println("do other!");
}
public void _jspService(HttpServletRequest request,HttpServletResponse response){
dosome();
System.out.println("servlet's service method execute!");
int j = 100;
System.out.println("j = " + j);
System.out.println("i = " + i);
}
}
3. JSP表达式(expression)
- 表达式语法,具有输出功能,输出到浏览器上
表达式的语法格式:
<%= 表达式 %>
- <%= %> 等同于 out.print();
- <%=“Hello World!”%> 等同于 out.print(“Hello World!”);
- <%=1+1%> 等同于 out.print(1+1);
- <%=“1+1”%> 等同于 out.print(“1+1”);
- <%= %>中的代码不能以“;”结尾,否则就 out.print(xxx;);显然是没有这种语法的。
五、JSP指令(directive)
- JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。
- 为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分
指令语法格式:
<%@ 指令名 属性名=属性值 属性名=属性值..... %>
JSP中的三种指令标签:
指令 | 描述 |
---|---|
<%@ page … %> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include … %> | 包含其他文件 |
<%@ taglib … %> | 引入标签库的定义 |
1.Page指令(页面指令)
- Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
Page指令的语法格式:
<%@ page attribute="value" %>
- importl 属性(翻译生成java语言中的import语句)
<%@page import=”java.util.Date,java.util.ArrayList”%>
- contentType属性(指定JSP页面响应内容类型)
<%@page contentType=”text/html”%>
- pageEncoding属性(指定JSP页面响应的页面字符编码)
<%@page pageEncoding=”UTF-8”%>
- session属性(指定当前JSP页面是否可以使用session这个内置对象)
<%@page session=”false”%> session内置对象不可用
<%@page session=”true”%> session内置对象可用(缺省的)
- errorPage属性(指定当前JSP页面发生错误之后跳转的资源路径)
<%@page contentType=“text/html; charset=UTF-8” errorPage="/error.jsp"%>
- isErrorPage属性(指定当前JSP页面是一个错误页面,这样才能使用内置对象exception)
<%@page contentType=“text/html; charset=UTF-8” isErrorPage=“true”%>
- isErrorPage = “false” 表示内置对象exception无法使用【缺省情况下是false】
- isErrorPage = “true” 表示内置对象exception可以使用
- isELIgnored属性指定当前页面中如果有EL表达式是否忽略,true表示忽略,false表示不忽略
2. Include指令(包含指令)
Include指令语法格式:
<%@include file="filePath"%>
- JSP include 指令用于通知 JSP 引擎在翻译当前 JSP 页面时,将其他文件中的内容合并进当前 JSP 页面转换成的 Servlet 源文件中,这种在源文件级别进行引入的方式,称为静态引入。
- 当前 JSP 页面与静态引入的文件紧密结合为一个 Servlet。
- 因此,在所包含的文件中不能使用 html、body 标记,否则会因为与原有的 JSP 文件有相同标记而产生错误。另外,因为原文件和被包含文件可以相互访问彼此定义的变量和方法,所以要避免变量和方法在命名上产生冲突。
- 这些文件可以是 JSP 页面、HTML 页面、文本文件或是一段 Java 代码。
- file 属性指定被包含的文件,不支持任何表达式,例如下面是错误的用法:
<% String f="top.html"; %>
<%@ include file="<%=f %>" %>
- 不可以在 file 所指定的文件后接任何参数,如下用法也是错误的:
<%@ include file="top.jsp?name=zyf" %>
- 如果 file 属性值以“/”开头,将在当前应用程序的根目录下查找文件;如果是以文件名或文件夹名开头,将在当前页面所在的目录下查找文件。
- include实现原理:
- 编译期包含
- a.jsp包含b.jsp,底层共生成一个java源文件,一个class字节码文件,翻译期包含/编译期包含/静态联编
- 静态联编的时候,多个jsp中可以共享同一个局部变量,因为最终翻译之后service方法只有一个。
3. Taglib指令(标签库指令)
Taglib指令语法格式:
<%@taglib attribute="value" %>
- 为了让JSP看起来更加的专业(只做页面展示),减少jsp页面中java代码的数量,我们引入了标签库,使用了标签库之后JSP程序中不再出现太多的java程序了,这样JSP页面看起来主要工作就是页面展示。
六、JSP动作元素(action)
- 与JSP指令元素不同的是,JSP动作元素在请求处理阶段起作用。
- 利用JSP动作可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
动作语法格式:
<jsp:动作名 属性名=属性值 属性名=属性值....></jsp:动作名>
JSP中几种常用的动作元素:
动作元素 | 描述 |
---|---|
jsp:include | 在页面被请求的时候引入一个文件 |
jsp:forward | 把请求转到一个新的页面 |
jsp:useBean | 寻找或者实例化一个JavaBean |
jsp:setProperty | 设置JavaBean的属性 |
jsp:getProperty | 输出某个JavaBean的属性 |
1. JSP include动作元素
include动作元素语法格式:
<jsp:include page="relative URL"></jsp:include>
- include 动作用于把另外一个文件的输出内容插入当前 JSP 页面的输出内容中,这种在 JSP 页面执行时引入的方式称为动态引入,这样,主页面程序与被包含文件是彼此独立的,互不影响。
实例代码:
以下我们定义两个文件a.jsp和b.jsp,代码如下所示:
a.jsp文件代码:
<%@page contentType="text/html; charset=UTF-8"%>
<html>
<head>
<title>include动作</title>
</head>
<body>
<jsp:include page="/b.jsp"></jsp:include>
</body>
</html>
b.jsp代码:
<h1 align="center"><font color="red">hello...</font></h1>
- JSP include动作实现原理
- a.jsp包含b.jsp,底层会分别生成两个java源文件,两个class字节码文件
- 编译阶段并没有包含,编译阶段是两个独立的class字节码文件,生成两个Servlet,两个独立的service方法
- 使用include动作属于运行阶段包含, 实际上是在运行阶段a中的service方法调用了b中的service方法,达到了包含效果
- a.jsp包含b.jsp,若两个jsp文件中有重名的变量,只能使用动态包含。其余都可以使用静态包含。
- include动作完成的动态包含,被称为动态联编。
- jsp:indude动作与前面讲解的 include 指令作用类似,现将它们之间的差异总结如下:
- 1. 属性不同:
- include指令通过file属性来指定包含页面,不支持任何表达式
- jsp:include动作是通过 page 属性来指定被包含页面的,该属性支持 JSP 表达式
- 2. 处理方式不同:
- 使用 include 指令包含文件时,被包含文件的内容会原封不动地插入到包含页中使用该指令的位置,然后 JSP 编译器再对这个合成的文件进行翻译,所以最终编译后的文件只有一个。
- 而使用jsp:include动作包含文件时,只有当该标记被执行时,程序才会将请求转发到(注意是转发,而不是请求重定向)被包含的页面,再将其执行结果输出到浏览器中,然后重新返回到包含页来继续执行后面的代码。因为服务器执行的是两个文件,所以 JSP 编器将对这两个文件分别进行编译。
- 3. 包含方式不同:
- include 指令的包含过程为静态包含,因为在使用 include 指令包含文件时,服务器最终执行的是将两个文件合成后由 JSP 编译器编译成的一个 Class 文件,所以被包含文件的内容应是固定不变的,若改变了被包含的文件,则主文件的代码就发生了改变,因此服务器会重新编译主文件。
- jsp:include动作的包含过程为动态包含,通常用来包含那些经常需要改动的文件。因为服务器执行的是两个文件,被包含文件的改动不会影响主文件,因此服务器不会对主文件重新编译,而只须重新编译被包含的文件即可。并且对被包含文件的编译是在执行时才进行的,也就是说,只有当jsp:include动作被执行时,使用该标记包含的目标文件才会被编译,否则,被包含的文件不会被编译。
2. JSP forward 动作元素
forward 动作元素语法格式:
<jsp:forward page="Relative URL" />
- jsp:forward动作把请求转到另外的页面,jsp:forward标记只有一个属性page。
- 当动作标记被执行后,当前的页面将不再被执行,而是去执行该标记指定的目标页面,但是,用户此时在地址栏中看到的仍然是当前网页的地址,而内容却已经是转向的目标页面了。
- forward 动作实现的是请求的转发操作,而不是请求重定向。
<jsp:forward page="/index2.jsp" />
//等同于
request.getRequestDispatcher("/index2.jsp").forward(request,response);
它们之间的一个区别就是:
- 进行请求转发时,存储在 request 对象中的信息会被保留并被带到目标页面中;
- 而请求重定向是重新生成一个 request 请求,然后将该请求重定向到指定的 URL,所以,事先储存在 request 对象中的信息都不存在了。
实例代码:
- 创建主页面index.jsp,通过表单输入用户名和密码,单击“登录”按钮,利用 jsp:forward 动作标记跳转到页面 target.jsp。具体代码如下:
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<body>
<form action=" " method="post" name="Form"> <!--提交给本页处理-->
用户名:<input name="UserName" type="text" /> <br/>
密 码:<input name="UserPwd" type="text" /> <br/>
<input type="submit" value="登录" />
</form>
<%
//当单击“登录”按钮时,调用Form1.submit()方法提交表单至本文件,
//用户名和密码均不为空时,跳转到targe.jsp,并且把用户名和密码以参数形式传递
String s1=null,s2=null;
s1=request.getParameter("UserName");
s2=request.getParameter("UserPwd");
if(s1!=null && s2!=null)
{
%>
<jsp:forward page="target.jsp" >
<jsp:param name="Name" value="<%=s1%>" />
<jsp:param name="Pwd" value="<%=s2%>" />
</jsp:forward >
<%
}
%>
</body>
</html>
- 创建所转向的目标文件target.jsp,具体代码如下:
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<body>
<%
String strName=request.getParameter("Name");
String strPwd=request.getParameter("Pwd");
out.println(strName+"您好,您的密码是:"+strPwd);
%>
</body>
</html>
3. JSP useBean动作元素
- jsp:useBean动作标记用于在 JSP 页面中创建 bean 实例,并且通过设置相关属性,可以将该实例存储到指定的范围。如果在指定的范围已经存在该 bean 实例,那么将使用这个实例,而不会重新创建。
useBean动作元素语法格式:
<jsp:useBean id="变量名" class="package.className" scope="page|request|session|application"...></jsp:useBean>
- 如果多个页面中共享这个 bean 实例,可将 scope 属性设置为 session
七、JSP九大内置对象
- JSP内置对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。JSP内置对象也被称为预定义变量。
JSP所支持的九大内置对象:
内置对象 | 描述 |
---|---|
request | HttpServletRequest类的实例 |
response | HttpServletResponse类的实例 |
out | PrintWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,代表页面上下文,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
1. request对象
- 每当客户端请求一个JSP页面时,JSP引擎就会制造一个新的request对象来代表这个请求。
- 客户端可通过 HTML 表单或在网页地址后面提供参数的方法提交数据,然后通过 request 对象的相关方法来获取这些数据。
- request 对象封装了客户端的请求信息,包括用户提交的信息以及客户端的一些信息,服务端通过 request 对象可以了解到客户端的需求,然后做出响应。
request对象常用方法:
方法 | 描述 |
---|---|
Object getAttribute(String name) | 用于返回由 name 指定的属性值,如果指定的属性值不存在,则返回一个 null 值 |
void setAttribute(String key,Object obj) | 设置属性的属性值 |
Enumeration getAttributeNames() | 用于返回 request 对象的所有属性的名称集合 |
String getParameter(String name) | 用于获取客户端传送给服务器端的参数。主要由 name 指定,通常是表单中的参数 |
Enumeration getParameterNames() | 用于获取客户端传送的所有参数的名字集合 |
String getParameterValues(String name) | 用于获得指定参数的所有值,由 name 指定 |
String setCharacterEncoding() | 用于设置请求正文中所使用的字符编码 |
String getMethod() | 用于获得客户端向服务器端传送数据的参数方法,主要有两个,分别是 get() 和 post() |
cookie[] get Cookie() | 用于获取所有的 Cookie 对象 |
- 获取用户信息
实例代码:
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>
request对象获取客户信息
</title>
</head>
<body>
客户提交信息的方式:<%=request.getMethod() %> <br/>
使用的协议:<%=request.getProtocol() %> <br/>
获取提交数据的客户端IP地址:<%=request.getRemoteAddr() %> <br/>
获取服务器端的名称:<%=request.getServerName() %> <br/>
获取服务器端口号:<%=request.getServerPort() %> <br/>
获取客户端的机器名称:<%=request.getRemoteHost() %> <br/>
</body>
</html>
-
获取请求参数
-
用户借助表单向服务器提交数据,完成用户与网站之间的交互,表单中包含文本框、列表、按钮等输入标记。当用户在表单中输入信息后,单击 提交 按钮提交给服务器处理。
-
用户提交的表单数据存放在 request 对象里,通常在 JSP 代码中用 getParameter() 或者 getParameterValues() 方法来获取表单传送过来的数据,前者用于获取单值,如文本框、按钮等;后者用于获取数组,如复选框或者多选列表项。使用格式如下:
String getParameter(String name);
String[] getParameterValues(String name);
以上两种方法的参数 name 与 HTML 标记的 name 属性对应,如果不存在,则返回 null。
- 修改字符编码
- 利用 request 的方法获取表单数据时,默认情况下,字符编码为 ISO-8859-1,所以,当获取客户提交的汉字字符时,会出现乱码问题,必须进行特殊处理。
在超链接中传递中文参数:
<a href="目标地址?参数名1=<%=URLEncoder.encode("中文值1")&参数名2=值2
%>>请求参数的值</a>
通过表单或< jsp:param/> 传递中文参数:
<jsp:include page="index.jsp">
<jsp:param name="num1" value="张三"/>
</jsp:include>
处理乱码问题:
<%
request.setCharacterEncoding("GBK"); //设置编码格式为中文编码,或者utf-8
%>
<%=new String(request.getParameter("name").getBytes("iso-8859-1"),"UTF-8") %>
- 在作用域中管理属性
- 通过setAttribute()方法可以在resquest对象的属性列表中添加一个属性,然后在request对象的作用域范围内通过getAttribute()方法将其取出,此外还可以使用removeAttribute()方法将一个属性删除。
设置转发数据的格式:
request.setAttribute("key",value);
获取转发数据的格式:
request.getAttribute("key");
- 在页面使用 request 对象的 setAttribute(“key”,value) 方法,可以把数据 value 设定在 request 范围内。请求转发后的页面使用 getAttribute(“key”) 就可以取得数据 value。
- 这一对方法在不同的请求之间传递数据,而且从上一个请求到下一个请求必须是转发请求(使用<jsp: forward >动作来实现),即保存的属性在 request 属性范围(request scope)内,而不能是重定向请求(使用 response.sendRedirect() 或者超级链接来实现)。
实例代码:
<!--a.jsp-->
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>
request对象在作用域中管理属性
</title>
</head>
<body>
<% request.setAttribute("str","欢迎学习request对象的使用方法!"); %>
<jsp:forward page="b.jsp"/>
</body>
</html>
<!--b.jsp-->
<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>
request对象在作用域中管理属性
</title>
</head>
<body>
<% out.println("页面转发后获取的属性值:"+request.getAttribute("str")); %>
</body>
</html>
运行结果图如下:
在 a.jsp 中,若将语句<jsp:forward page=“b.jsp”/>改成response.sendRedirect(“b.jsp”)或者 《a href=“b.jsp”》 跳转《/a》,就不能获得 request 范围内的属性值。
- 获取Cookie
- cookie是小段的文本信息,通过使用cookie可以标识用户身份、记录用户名及密码、跟踪重复用户。
- cookie在服务器端生成并发送给浏览器,浏览器将cookie的key/value保存到某个指定的目录中,服务器的名称与值可以由服务器端定义。
- 通过 request 对象的 getCookies() 方法获取 Cookie 对象的集合,获取 Cookie 的方法如下:
Cookie[] cookie=request.getCookies();
- 通过cookie对象的getName()方法可获取指定名称的cookie。
String names = cookies[i].getName()
- 通过getValue()方法可获取cookie对象的值。
- 通过 response 对象的 addCookie() 方法添加一个 Cookie 对象。添加 Cookie 的方法如下:
String value = response.addCookie(Cookie cookie)
2. response对象
- response 对象和 request 对象相对应,用于响应客户请求,主要是将JSP容器处理过的对象传回到客户端。response对象只在JSP页面内有效。
response对象常用方法:
方法 | 描述 |
---|---|
void addCookie(Cookie cookie) | 添加一个Cookie对象,用来保存客户端用户信息 |
void sendError(int xc[,String msg]) | 向客户端发送错误信息 |
void sengRedirect(java.lang.String location) | 重定向网页 |
void set BufferSize(int size) | 设置缓冲区大小:respones.setBufferSize(0);(不缓冲) |
void setCotentType(String type) | 设置响应的 MIME 类型 |
void setHeader(String name,String value) | 设置指定的HTTP文件的值,如果该值已经存在,则新值会覆盖原有的旧值. respones.setHeader(“refresh”,“5”);设置网页每5秒自动刷新一次。 |
- 设置页面自动刷新以及定时跳转
- 实现页面一秒钟刷新一次,设置语句如下:
response.setHeader("refresh","1");
- 实现页面定时跳转,如 2 秒钟后自动跳转到URL所指的页面,设置语句如下:
response.setHeader("refresh","2:URL=页面名称");
实例代码:实现秒表功能
<%@ page contentType="text/html;charset=utf-8" %>
<%@ page contentType="text/html;charset=utf-8" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>
response 对象设置页面自动刷新
</title>
</head>
<body>
<h2> response 对象设置页面自动刷新</h2>
<font size="5" color=blue> 数字时钟> </font> <br> <br>
<font size="3" color=blue> 现在时刻:<br>
<%
response.setHeader("refresh","1");
int y,m,d,h,mm,s;
Calendar c=Calendar.getInstance();
y=c.get(Calendar.YEAR); //年
m=c.get(Calendar.MONTH)+1; //月
d=c.get(Calendar.DAY_OF_MONTH); //日
h=c.get(Calendar.HOUR); //时(HOUR:十二小时制:HOUR_OF_DAY:十二四小时制)
mm=c.get(Calendar.MINUTE); //分
s=c.get(Calendar.SECOND); //分
out.println(y+"年"+m+"月"+d+"日"+h+"时"+mm+"分"+s+"秒");
%>
</font>
</body>
</html>
运行结果图如下:
3. session对象
- 客户与服务器之间的通信是通过 HTTP 协议完成的。HTTP 是一种无状态的协议,当客户向服务器发出请求,服务器接收请求并返回响应后,该连接就被关闭了。此时,服务器端不保留连接的有关信息,要想记住客户的连接信息,可以使用 JSP 提供的 session 对象。
- 用户登录网站时,系统将为其生成一个独一无二的 session 对象,用以记录该用户的个人信息。一旦用户退出网站,那么,所对应的 session 对象将被注销。session 对象可以绑定若干个用户信息或者 JSP 对象,不同的 session 对象的同名变量是不会相互干扰的。
- 当用户首次访问服务器上的一个 JSP 页面时,JSP 引擎便产生一个 session 对象,同时分配一个 String 类型的 ID 号,JSP 引擎同时将这个 ID 号发送到客户端,存放在 Cookie 中,这样,session 对象和客户端之间就建立了一一对应的关系。
- 当用户再次访问该服务器的其他页面时,不再分配给用户新的 session 对象,直到用户关闭浏览器,或者在一定时间(系统默认在 30 分钟内,但可在编写程序时,修改这个时间限定值或者显式地结束一个会话)客户端不向服务器发出应答请求,服务器端就会取消该用户的 session 对象,与用户的会话对应关系消失。当用户重新打开浏览器,再次连接到该服务器时,服务器为该用户再创建一个新的 session 对象。
session对象的常用方法:
方法 | 描述 |
---|---|
Object getAttribute(String name) | 获取指定名字的属性 |
Enumeration getAttributeName() | 获取 session 中全部属性的名字,一个枚举 |
public String getld() | 返回创建 session 时 JSP 引擎为它设置的唯一 ID 号 |
void invalidate() | 销毁 session 对象 |
void removeAttxibute(String name) | 删除指定名字的属性 |
void setAttribute(String name,String value) | 设定指定名字的属性值 |
创建session对象:
<%
String name = request.getParameter("name"); //获取用户填写的用户名
session.setAttribute("name",name); //将用户名保存在session对象中
%>
获取session对象:
<%
String name = (String)session.getAttribute("name");
//获取保存在session范围内的对象
%>
4. application对象
- application 对象用于保存应用程序的公用数据,服务器启动并自动创建 application 对象后,只要没有关闭服务器,application 对象就一直存在,所有用户共享 application 对象。
application对象的常用方法:
方法 | 描述 |
---|---|
getAttribute( String arg) | 获取 application 对象中含有关键字的对象 |
getAttributeNames() | 获取 application 对象的所有参数名字 |
setAttribute(String key,Object obj) | 将参数 Object 指定的对象 obj 添加到 application 对象中,并为添加的对象指定一个索引关键字 |
removeAttribute(java.lang.String name) | 根据名字删除 application 对象的参数 |
实例代码:application对象实现网页计数器
<%@ page import="java.lang.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>计数器</title>
</head>
<body>
<h2>application 对象实现网页计数器</h2>
<%
out.println("设置数值");
Integer intcount;
if (application.getAttribute("count")==null) {
intcount=1;
}else {
intcount=(Integer.valueOf(application.getAttribute("count").toString()));
}
application.setAttribute("name","张三");
application.setAttribute("count",intcount);
out.print("set name=张三");
out.print("<br>set count="+intcount+"<br>");
%>
<a href="gateppatter.jsp">计数器页面</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>gateppatter</title>
</head>
<body>
<br>获取用户名:<%=application.getAttribute("name")%>
<br>计数器
<%
int mycount=Integer.valueOf(application.getAttribute("count").toString()).intValue();
out.println(mycount);
application.setAttribute("count",Integer.toString(mycount+1));
%>
</body>
</html>
运行结果图如下:
5.out对象
- out 对象是一个输出流,用来向客户端输出数据,可以是各种数据类型的内容。同时,它还可以管理应用服务器上的输出缓冲区,缓冲区的默认值是 8KB,可以通过页面指令 page 来改变默认大小。
out对象的常用方法:
方法 | 描述 |
---|---|
void print(各种数据类型) | 将指定类型的数据输出到 HTTP 流,不换行 |
void println(各种数据类型) | 将指定类型的数据输出到 HTTP 流,并输出一个换行符 |
void newline | 输出换行字符 |
6. pageContext对象
- pageContext 是页面上下文对象。
- 它可以访问本页所有的 session,也可以取本页所在的 application 的某一属性值,它相当于页面中所有其他对象功能的集大成者,可以用它访问本页中所有的其他对象。
- pageContext 对象的主要作用是提供一个单一界面,以管理各种公开对象(如 session、application、config、request、response 等),提供一个单一的 API 来管理对象和属性。
- pageContext只能在同一个JSP页面中共享数据。可以获取include指令包含的jsp页面中存储的数据,但是不能获取include动作包含的jsp页面中存储的数据。范围是最小的。
pageContext 对象在实际 JSP 开发过程中很少使用,因为 request 和 response 等对象可以直接调用方法进行使用
7. config对象
- config 对象是 javax.servlet.ServletConfig 类的实例,表示 Servlet 的配置信息。
- 当一个 Servlet 初始化时,容器把某些信息通过此对象传递给这个 Servlet,这些信息包括 Servlet 初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个 ServletContext 对象),config 对象的应用范围是本页。
- 开发者可以在 web.xml 文件中为应用程序环境中的 Servlet 程序和 JSP 页面提供初始化参数。
8. page对象
- 这个对象就是页面实例的引用。它可以被看做是整个JSP页面的代表。
- page 对象是为了执行当前页面应答请求而设置的 Servlet 类的实体,即显示 JSP 页面自身,与类的 this 指针类似,使用它来调用 Servlet 类中所定义的方法,只有在本页面内才是合法的。
page对象的常用方法:
方法 | 描述 |
---|---|
class getClass() | 返回当前 Object 的类 |
int hashCode | 返回 Object 的 hash 代码 |
String toString | 把 Object 对象转换成 String 类的对象 |
boolean equals(Object obj) | 比较对象和指定的对象是否相等 |
9. exception 对象
- exception 对象包装了从先前页面中抛出的异常信息。它通常被用来产生对出错条件的适当响应。
对比JSP中的四个作用域对象
范围比较:pageContext < request < session < application
- pageContext : 在同一个JSP页面中共享数据,不能跨JSP页面
- request : 在同一个请求中共享数据 【使用较多】
- session : 在同一个会话中共享数据 【使用较多】
- application : 所有用户共享的数据可以放到应用范围中