说到最后,JSP其实还是一种对servlet的简化语言,所有的JSP页面最终都会被servlet容器编译成servlet类(其实就是java类),而至于什么是servlet容器,在此简单说下,仅从字面意思上看,它就是一种存放东西的容器,存放什么东西呢?存放维护和创建servlet相关的逻辑(懂C++的JSP新手注意:千万不要将这里的容器和C++中的VECTOR容器相混淆,这里的容器就是一个简单的存东西的容器)。而servlet的实现逻辑大体如下(5个方法):
- public void init(ServletConfig config) throws ServletException
- public void service(ServletRequest request, ServletResponse response)
- throws ServletException, java.io.IOException
- public void destroy()
- ServletConfig getServletConfig()
- public java.lang.String getServletInfo()
public void init(ServletConfig config) throws ServletException
public void service(ServletRequest request, ServletResponse response)
throws ServletException, java.io.IOException
public void destroy()
ServletConfig getServletConfig()
public java.lang.String getServletInfo()
最主要的方法就是init,service和destroy,它们是servlet对象的生存周期,当一个页面被编译成servlet类,再进行实例化后,这个页面就开始了真正的生命周期,servlet容器会先加载init方法进行初始化,初始化后才可进行接收和相应客户端的消息,之后容器会再加载service,这部分就是真正相应客户端请求的实现逻辑,它实现客户端的请求响应,然后动态生成HTML页面显示到客户端;而destory方法则是在servlet生命周期即将结束时进行的清理工作。
而事实上,Tomcat在大多数情况下充当servlet的容器,也就是说:在写完JSP代码后进行第一次执行时,tomcat(servlet容器)先将JSP代码翻译成servlet类(java代码),然后实例化该类,再调用该类的init,service,destory等进行生命周期服务。当客户端再进行第二次访问请求时,此时就没有servlet容器的翻译这一步了,因为之前翻译的java代码会一直保存,以便于后面的访问不再进行翻译,可大大提高访问效率。所以,JSP页面在第一次被访问时,其所花费的时间是最长的。
1.JSP语句的生明
JSP的声明语句格式<%! %>,,要注意,凡是用JSP声明的变量或函数,在servlet容器翻译成servlet类时,都将其翻译为servlet类的成员变量或函数;当JSP文件被翻译成servlet类后进行实例化时,所有的客户端访问的实例化servlet对象都是同一个对象,这意味着,如果试图对成员变量进行操作,那么其影响可谓是全局性的。来看下下面实例:
01.<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
02.<%
03.String path = request.getContextPath();
04.String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
05.%>
06.
07.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
08.<html>
09. <head>
10. <base href="<%=basePath%>">
11.
12. <title>My JSP 'index.jsp' starting page</title>
13. <meta http-equiv="pragma" content="no-cache">
14. <meta http-equiv="cache-control" content="no-cache">
15. <meta http-equiv="expires" content="0">
16. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17. <meta http-equiv="description" content="This is my page">
18. <!--
19. <link rel="stylesheet" type="text/css" href="styles.css">
20. -->
21. </head>
22. <%!
23. private int count = 0;
24. public int getCount()
25. {
26. count ++ ;
27. return count;
28. }
29. %>
30. <body>
31. <%
32. out.println("the value of count is: " + getCount());
33. %>
34.
35. </body>
36.</html>
这是一个简单的JSP程序,在第一次运行后,页面结果显示为:the value of count is: 1
而进行刷新页面时,每刷新一次,其count值都加1,显示结果也会改变:the value of count is: 2等等。
再从浏览器中看下HTLM源代码:
01.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
02.<html>
03. <head>
04. <base href="http://jxpc-001:8080/MyTest/">
05.
06. <title>My JSP 'index.jsp' starting page</title>
07. <meta http-equiv="pragma" content="no-cache">
08. <meta http-equiv="cache-control" content="no-cache">
09. <meta http-equiv="expires" content="0">
10. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
11. <meta http-equiv="description" content="This is my page">
12. <!--
13. <link rel="stylesheet" type="text/css" href="styles.css">
14. -->
15. </head>
16.
17. <body>
18. the value of count is: 1
19.
20. </body>
21.</html>
可以看到,凡是有关jsp声明相关的部分全部没有了,只剩下纯HTML代码。正好印证了前面一篇文章中所说过的话:
“容器会再加载service,这部分就是真正相应客户端请求的实现逻辑,它实现客户端的请求响应,然后动态生成HTML页面显示到客户端”
2.JSP的编译指令:include 和 page
至于上面的JSP文章中开头部分还有一行代码:
01.<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
这是一条编译指令,在JSP翻译成servlet类时,用来通知servlet容器的消息,以让其在翻译成servlet类时按照指定的额外要求进行翻译。
说到这,再来探讨下编译指令。常见的编译指令有3条:page(对当前页面的编译要求),include(包含其它页面),和tablib(自定义和访问),其声明方式为<%@ (指令) [属性 ="..." ] %>, 对于page指令,通常放在JSP文件开头处,一个JSP页面可出现多个page指令,如可将上面的page指令改为:
01.<%@ page language="java" import="java.util.*"% >
02.
03.<%@ page pageEncoding="ISO-8859-1"%>
两行语句来代替,其效果相同。
而对于include指令,<%@ include %>,这是个静态包含语句,servlet容器在包含时对其内容不进行任何检测就将其包含,若其文件内容有误,也在包含进来后进行翻译的时候才检测其内容的正误,这一点与C++中的预编译指令#define有些像,#define只是进行简单的替换,至于其正误,在代码编译时才能检测出来,而在这里<% @ include %>也只是先进行简单的包含,对于其内容要一直等到编译为servlet类时进行检测。
另外编写一个JSP文件,其内容如下:
01.<%@page import = "java.util.*" %>
02.<%=new Date() %>
在之前代码的<body>部分再加一行代码:
01.<%@include file="includeByIndex.jsp" %>
执行程序后,结果如下:
this is a new JSP page
Tue Aug 09 09:56:23 CST 2011
3.JSP的几种动作指令
在这里,我们再把之前的include语句替换成如下语句:
01.<jsp:forward page="includeByIndex.jsp"></jsp:forward>
includeByIndex.jsp的内容不变,则显示结果又如下:
Tue Aug 09 10:11:30 CST 2011
没有了之前的“this is a new JSP page”,这是因为这里的jsp:forword是个跳转语句,其可跳转到指定的静态或动态页面,或跳转到容器中的servlet。
在进行跳转时,还可以进行参数传递,如下:
01.<jsp:forward page="includeByIndex.jsp">
02. <jsp:param value="James" name="username"/>
03.</jsp:forward>
将includeByIndex.jsp的内容再改写如下:
01.<%@ page import="java.util.*"%>
02.<body>
03.<%out.println("the param of username is : "); %>
04.<%=request.getParameter("username") %>
05.<%out.println("now the time is: "); %>
06.<%=new Date() %>
07.</body>
最终页面上的结果为:
the param of username is : James now the time is: Tue Aug 09 10:19:40 CST 2011
至于接收参数的对象request,再这里先不介绍,以后再进行详细阐述。
我们继续将之前的讲解include源代码基础上再将include语句替换成如下语句:
01.<jsp:include page="includeByIndex.jsp"></jsp:include>
其页面显示结果为:
this is a new JSP page
Tue Aug 09 10:29:14 CST 2011
可以看到与没替换之前编译指令include执行效果差不多,那么它们的区别到底在哪呢?区别就在于:编译指令<%@include>只是简单的将源文件包含进来,然后进行执行,而<jsp:include>是个动作指令,它是在将源文件代码进行执行后,再将其结果包含进来进行显示(如果要包含的文件为静态文件,则直接进行显示),简单的说:<%@include>指令先包含,再执行,而<jsp:include>指令先执行,再包含。从servlet容器层面上来看,动态导入时,servlet类中会将<jsp:include>翻译为一条简单的包含语句:
01.org.apache.jasper.runtime.JspRuntimeLibrary.include(request , response ,"includeByIndex.jsp" , out);
而<%@include>会被容器翻译为JAVA源代码,然后与servlet类一起构成整个文件。
到这里,JSP单文件处理内容已经差不多了,接下来就是JSP与JAVA类的混合编码,开始步入将业务逻辑与页面实现分离的阶段。
首先来看下3种动作指令:useBean,setProperty,getProperty,其中useBean是进行类的对象的声明语句,setProperty和getProperty是对页类的属性进行操作的语句。
我们先来声明一个自己的JAVA类,代码如下所示:
01.package com.user;
02.
03.public class userInformation {
04. private String userName;
05. private String userPassword;
06.
07. public String getUserName() {
08. return userName;
09. }
10. public void setUserName(String userName) {
11. this.userName = userName;
12. }
13. public String getUserPassword() {
14. return userPassword;
15. }
16. public void setUserPassword(String userPassword) {
17. this.userPassword = userPassword;
18. }
19.}
在页面中的<body>部分代码如下:
01.<body>
02. <jsp:useBean id="user" class="com.user.userInformation" scope="page"></jsp:useBean>
03. <jsp:setProperty property="userName" name="user" value="James"/>
04. <jsp:setProperty property="userPassword" name="user" value="123456"/>
05. <jsp:getProperty property="userName" name="user"/>
06. <jsp:getProperty property="userPassword" name="user"/>
07. </body>
该JSP文件的执行结果为:
James 123456
其中<jsp:useBean>的属性id为对象名,class为类名,scope为对象的生存周期,有如下四个可选项:
page:仅在当前页面有效;
request::在一次请求范围内有效,即:如果页面从一个页面转到另一个页面,那么当前对象失效;
session:在一次连接范围内有效,如果和服务器断开连接,则当前对象失效;
application:从服务器启动到结束一直有效。
(至于这几个声明周期,其具体内容较多,在此先不进行详细阐述,会在下一篇文章中介绍。)
<jsp:setProperty>属性property为类的属性名,name为对象名,value为值。
本篇依然为基础篇,主要讲解Jsp的9个内置对象。Jsp的内置对象为Servlet API的类或接口的实例化,它们的实例化过程由Jsp标准自动进行,意即:我们可以直接使用这些对象,而不需要声明它,这些内置对象分别为:application, config,response,request,exception,out,page,pagecontext,session;接下来,我就分别对几个主要对象的特性进行详细阐述:
1.application对象
它是javax.servlet.ServletContext类的对象,一般来说,它就代表整个WEB应用,对于它的属性值,在整个WEB应用(JSP或Servlet类)中都是公用的,最常用的方法是:setAttribute(name,value)和getAttribute(name);为此来做个测试:在同一个WEB工程中编写两个JSP文件,index.jsp如下:
- <%@ page language="java" import="java.util.*" %>
- <%@ page pageEncoding="ISO-8859-1"%>
- <html>
- <%!
- private int count = 0;
- public Integer getCount()
- {
- count ++ ;
- return count;
- }
- %>
- <body>
- <%
- application.setAttribute("count",getCount().toString());
- out.println("the value of count is :"+count); %>
- </body>
- </html>
<%@ page language="java" import="java.util.*" %> <%@ page pageEncoding="ISO-8859-1"%> <html> <%! private int count = 0; public Integer getCount() { count ++ ; return count; } %> <body> <% application.setAttribute("count",getCount().toString()); out.println("the value of count is :"+count); %> </body> </html>
test_application.jsp内容如下:
- <%@page language="java" contentType="text/html; charset=ISO-8859-1" %>
- <html>
- <head>
- <title>测试application</title>
- </head>
- <body>
- <%out.println("get the value of count,the count is a field of application,value: "); %>
- <%=application.getAttribute("count")%>
- </body>
- </html>
<%@page language="java" contentType="text/html; charset=ISO-8859-1" %> <html> <head> <title>测试application</title> </head> <body> <%out.println("get the value of count,the count is a field of application,value: "); %> <%=application.getAttribute("count")%> </body> </html>
我们先启动服务器,访问http://localhost:8080/index.jsp,其结果如下:the value of count is :2,
每刷新一次页面,count的值就增1,此时我们再访问http://localhost:8080/test_application.jsp,其结果显示如下:
get the value of count,the count is a field of application,value: 2
没有进行任何参数传递,也没有直接获取javabean的属性,而是通过application对象,先设置属性(application.setAttribute("count",getCount().toString());),再从另一个页面中获得属性(application.getAttribute("count"))就能做到属性的全局共享,这便是使用application对象的作用。
application对象的另外一个强大作用就是能用来解析WEB.XML的配置信息,以下就是一个完整的连接和查询mysql数据库的例子,而访问数据库的url,密码,用户名等信息,均存储在web.xml中,在JSP文件中用application对象读取参数属性。
- <%@ page language="java" import="java.util.*" %>
- <%@ page pageEncoding="ISO-8859-1"%>
- <%@page import="java.sql.SQLException"%>
- <%@page import="java.net.ConnectException"%>
- <%@page import="java.sql.DriverManager"%>
- <%@page import="java.sql.*" %>
- <html>
- <body>
- <%
- Connection conn=null;
- Statement state=null;
- ResultSet rs=null;
- String driver=application.getInitParameter("driver");
- String url=application.getInitParameter("url");
- String user=application.getInitParameter("user");
- String password=application.getInitParameter("password");
- try{
- Class.forName(driver);
- conn=DriverManager.getConnection(url,user,password);
- }catch(SQLException e) {
- out.println("failed to connect the db");
- } catch(ClassNotFoundException e){
- out.println("can't find the driver class");
- }
- try{
- state=conn.createStatement();
- String queryAll="select*from user_information";
- rs=state.executeQuery(queryAll);
- while(rs.next())
- {
- int userid=rs.getInt(1);
- String username=rs.getString(2);
- String userpassword=rs.getString(3);
- out.println("user id is: "+userid);
- out.println("user name is: "+username);
- out.println("user password is: "+userpassword);
- }
- }catch(SQLException e){
- out.println("research fialed!");
- }
- try{
- if(rs != null){
- rs.close();
- }
- if(state != null){
- state.close();
- }
- if(conn != null){
- conn.close();
- }
- }catch(Exception e){
- out.println("error when close db");
- }
- %>
- </body>
- </html>
<%@ page language="java" import="java.util.*" %> <%@ page pageEncoding="ISO-8859-1"%> <%@page import="java.sql.SQLException"%> <%@page import="java.net.ConnectException"%> <%@page import="java.sql.DriverManager"%> <%@page import="java.sql.*" %> <html> <body> <% Connection conn=null; Statement state=null; ResultSet rs=null; String driver=application.getInitParameter("driver"); String url=application.getInitParameter("url"); String user=application.getInitParameter("user"); String password=application.getInitParameter("password"); try{ Class.forName(driver); conn=DriverManager.getConnection(url,user,password); }catch(SQLException e) { out.println("failed to connect the db"); } catch(ClassNotFoundException e){ out.println("can't find the driver class"); } try{ state=conn.createStatement(); String queryAll="select*from user_information"; rs=state.executeQuery(queryAll); while(rs.next()) { int userid=rs.getInt(1); String username=rs.getString(2); String userpassword=rs.getString(3); out.println("user id is: "+userid); out.println("user name is: "+username); out.println("user password is: "+userpassword); } }catch(SQLException e){ out.println("research fialed!"); } try{ if(rs != null){ rs.close(); } if(state != null){ state.close(); } if(conn != null){ conn.close(); } }catch(Exception e){ out.println("error when close db"); } %> </body> </html>
web.xml的完整信息如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- <context-param>
- <param-name>driver</param-name>
- <param-value>com.mysql.jdbc.Driver</param-value>
- </context-param>
- <context-param>
- <param-name>user</param-name>
- <param-value>root</param-value>
- </context-param>
- <context-param>
- <param-name>password</param-name>
- <param-value>900622</param-value>
- </context-param>
- <context-param>
- <param-name>url</param-name>
- <param-value>jdbc:mysql://localhost:3306/test_db</param-value>
- </context-param>
- </web-app>
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>driver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </context-param> <context-param> <param-name>user</param-name> <param-value>root</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>900622</param-value> </context-param> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test_db</param-value> </context-param> </web-app>
页面执行结果为:user id is: 1 user name is: James user password is: 123456
2. pageContext对象
pageContext对象可以用来访问和设置各种范围的属性(包括page,request,session和application),事实上,如果给各种范围的属性设置成相同的属性名,那么各属性是互不影响的,这就相当于C++中同名变量在不同的生存范围内互不影响(如同名的全局变量和局部变量),而pageContext通常用来获得和设置各种范围的属性值,看下面实例:
- <body>
- <%
- //使用不同内置对象设置不同范围属性
- pageContext.setAttribute("name","page_James"); //设置page范围属性
- request.setAttribute("name","request_James"); //设置request范围属性
- session.setAttribute("name","session_James"); //设置session范围属性
- application.setAttribute("name","application_James"); //设置application范围属性
- //使用pageContext设置不同范围属性
- pageContext.setAttribute("age","30"); //不指定属性的范围时默认为page范围
- pageContext.setAttribute("age","40",pageContext.REQUEST_SCOPE);
- pageContext.setAttribute("age","50",pageContext.SESSION_SCOPE);
- pageContext.setAttribute("age","60",pageContext.APPLICATION_SCOPE);
- %>
- <%="page范围的name值:"+(String)pageContext.getAttribute("name",pageContext.PAGE_SCOPE)%><br/>
- <%="page范围的age值: "+(String)pageContext.getAttribute("age",pageContext.PAGE_SCOPE) %><br/>
- <%="request范围name值: "+(String)pageContext.getAttribute("name",pageContext.REQUEST_SCOPE)%><br/>
- <%="request范围age值:"+(String)pageContext.getAttribute("age",pageContext.REQUEST_SCOPE) %><br/>
- <%="session范围name值: "+(String)pageContext.getAttribute("name",pageContext.SESSION_SCOPE) %><br/>
- <%="session范围age值:"+(String)pageContext.getAttribute("age",pageContext.SESSION_SCOPE) %><br/>
- <%="application范围name值:"+(String)pageContext.getAttribute("name",pageContext.APPLICATION_SCOPE) %><br/>
- <%="application范围name值:"+(String)pageContext.getAttribute("age",pageContext.APPLICATION_SCOPE) %>
- </body>
<body>
<%
//使用不同内置对象设置不同范围属性
pageContext.setAttribute("name","page_James"); //设置page范围属性
request.setAttribute("name","request_James"); //设置request范围属性
session.setAttribute("name","session_James"); //设置session范围属性
application.setAttribute("name","application_James"); //设置application范围属性
//使用pageContext设置不同范围属性
pageContext.setAttribute("age","30"); //不指定属性的范围时默认为page范围
pageContext.setAttribute("age","40",pageContext.REQUEST_SCOPE);
pageContext.setAttribute("age","50",pageContext.SESSION_SCOPE);
pageContext.setAttribute("age","60",pageContext.APPLICATION_SCOPE);
%>
<%="page范围的name值:"+(String)pageContext.getAttribute("name",pageContext.PAGE_SCOPE)%><br/>
<%="page范围的age值: "+(String)pageContext.getAttribute("age",pageContext.PAGE_SCOPE) %><br/>
<%="request范围name值: "+(String)pageContext.getAttribute("name",pageContext.REQUEST_SCOPE)%><br/>
<%="request范围age值:"+(String)pageContext.getAttribute("age",pageContext.REQUEST_SCOPE) %><br/>
<%="session范围name值: "+(String)pageContext.getAttribute("name",pageContext.SESSION_SCOPE) %><br/>
<%="session范围age值:"+(String)pageContext.getAttribute("age",pageContext.SESSION_SCOPE) %><br/>
<%="application范围name值:"+(String)pageContext.getAttribute("name",pageContext.APPLICATION_SCOPE) %><br/>
<%="application范围name值:"+(String)pageContext.getAttribute("age",pageContext.APPLICATION_SCOPE) %>
</body>
其页面执行结果如下:
page范围的name值:page_James
page范围的age值: 30
request范围name值: request_James
request范围age值:40
session范围name值: session_James
session范围age值:50
application范围name值:application_James
application范围name值:60
3. request对象
request对象是个很重要的对象,它被用于封装一次的用户请求参数,请求参数可以是表单值,可以是以request对象设置的属性值,也可以是url地址中所附带的少量字符串参数。 我们来看下面实例:
index.jsp的body部分
- <body>
- <%
- ArrayList<String> list = new ArrayList<String>() ;
- list.add("this");
- list.add(" is");
- list.add(" the");
- list.add(" list");
- for(int i = 0 ;i<list.size();i++)
- {
- out.println(list.get(i));
- }
- request.setAttribute("list",list);
- %>
- <form action="request.jsp" id="form" method="post" >
- 用户名:<input type="text" name="username"><hr/>
- 密 码:<input type="text" name="userpwd"><hr/>
- <input type="submit" value="提 交">
- </form>
- </body>
<body>
<%
ArrayList<String> list = new ArrayList<String>() ;
list.add("this");
list.add(" is");
list.add(" the");
list.add(" list");
for(int i = 0 ;i<list.size();i++)
{
out.println(list.get(i));
}
request.setAttribute("list",list);
%>
<form action="request.jsp" id="form" method="post" >
用户名:<input type="text" name="username"><hr/>
密 码:<input type="text" name="userpwd"><hr/>
<input type="submit" value="提 交">
</form>
</body>
request.jsp的body部分:
- <body>
- <%="user name is: "+request.getParameter("username") %><br/>
- <%="user password is: "+request.getParameter("userpwd") %><br/>
- <%
- ArrayList<String> list = (ArrayList<String>)request.getAttribute("list");
- for(int i = 0 ;i<list.size() ; i++)
- {
- out.println(list.get(i));
- }
- %>
- </body>
<body>
<%="user name is: "+request.getParameter("username") %><br/>
<%="user password is: "+request.getParameter("userpwd") %><br/>
<%
ArrayList<String> list = (ArrayList<String>)request.getAttribute("list");
for(int i = 0 ;i<list.size() ; i++)
{
out.println(list.get(i));
}
%>
</body>
大概看来,这段代码应该没错,如果我们在“用户名”中输入:james,在“密码”中输入:admin,那么,我们预料的显示结果应该是
user name is :james
user password is: admin
this is the list
而事实上,请求提交后,页面出错,显示一堆错误信息。
在这里要注意,提交请求和页面跳转是两个不同的概念,范围属性和请求参数也是两个不同的概念,提交请求后,请求参数会被servlet封装到request对象中,这一点毋庸置疑,但不会将属性也封装到servlet中,只有当发生< jsp:forward>跳转时,才会将属性提交到要转发的页面,如果我们将index.jsp改为如下:
- <body>
- <%
- ArrayList<String> list = new ArrayList<String>() ;
- list.add("this");
- list.add(" is");
- list.add(" the");
- list.add(" list");
- for(int i = 0 ;i<list.size();i++)
- {
- out.println(list.get(i));
- }
- request.setAttribute("list",list);
- %>
- <%
- ArrayList<String> list2 = new ArrayList<String>();
- list2 = (ArrayList<String>)pageContext.getAttribute("list",pageContext.REQUEST_SCOPE);
- for(int i = 0 ;i<list2.size() ; i++)
- {
- out.println(list.get(i));
- }
- %>
- <jsp:forward page="request.jsp"></jsp:forward> // !!!!!注意多加了这一句!!!
- <form action="request.jsp" id="form" method="post" >
- 用户名:<input type="text" name="username"><hr/>
- 密 码:<input type="text" name="userpwd"><hr/>
- <input type="submit" value="提 交">
- </form>
- </body>
<body>
<%
ArrayList<String> list = new ArrayList<String>() ;
list.add("this");
list.add(" is");
list.add(" the");
list.add(" list");
for(int i = 0 ;i<list.size();i++)
{
out.println(list.get(i));
}
request.setAttribute("list",list);
%>
<%
ArrayList<String> list2 = new ArrayList<String>();
list2 = (ArrayList<String>)pageContext.getAttribute("list",pageContext.REQUEST_SCOPE);
for(int i = 0 ;i<list2.size() ; i++)
{
out.println(list.get(i));
}
%>
<jsp:forward page="request.jsp"></jsp:forward> // !!!!!注意多加了这一句!!!
<form action="request.jsp" id="form" method="post" >
用户名:<input type="text" name="username"><hr/>
密 码:<input type="text" name="userpwd"><hr/>
<input type="submit" value="提 交">
</form>
</body>
那么request.jsp的显示内容将又会为:
user name is:null
user password is:null
this is the list
index.jsp中未提交请求前就发生跳转,所以name和password值没有设置,而forward跳转会传递属性,所以会在跳转页面request.jsp中正常接收。
4. response和out对象
response对象和out对象都是用来向页面输出信息的流对象,其不同之处在于:out对象只能输出字符流(只能输出文字),却不能输出字节流(如位图),而response对象却可以做到这一点;在大多数情况下,out完全可以替代response的作用,而有时候response的功能却不容忽视,甚至起关键作用:如可以创建cookie,可以设置定时刷新的页面,可以不使用forward跳转来实现不带属性的跳转。 以下来看一下response创建cookie的示例:
在index.jsp中代码如下:
- <body>
- <form action="request.jsp" id="form" method="post" >
- 用户名:<input type="text" name="username"><hr/>
- 密 码:<input type="text" name="userpwd"><hr/>
- <input type="submit" value="提 交">
- </form>
- </body>
<body>
<form action="request.jsp" id="form" method="post" >
用户名:<input type="text" name="username"><hr/>
密 码:<input type="text" name="userpwd"><hr/>
<input type="submit" value="提 交">
</form>
</body>
在request.jsp中代码如下:
- <body>
- <%
- String userName = request.getParameter("username");
- String userPassword = request.getParameter("userpwd");
- Cookie nameCookie = new Cookie("username",userName); //创建cookie
- nameCookie.setMaxAge(24*3600);//设置生存时间为24小时
- Cookie pwdCookie = new Cookie("userpwd",userPassword);
- pwdCookie.setMaxAge(24*3600);
- response.addCookie(nameCookie); //添加cookie
- response.addCookie(pwdCookie);
- %>
- <jsp:forward page="prove.jsp"></jsp:forward>
- </body>
<body>
<%
String userName = request.getParameter("username");
String userPassword = request.getParameter("userpwd");
Cookie nameCookie = new Cookie("username",userName); //创建cookie
nameCookie.setMaxAge(24*3600);//设置生存时间为24小时
Cookie pwdCookie = new Cookie("userpwd",userPassword);
pwdCookie.setMaxAge(24*3600);
response.addCookie(nameCookie); //添加cookie
response.addCookie(pwdCookie);
%>
<jsp:forward page="prove.jsp"></jsp:forward>
</body>
这样,凡是客户端输出用户名和密码的话,其便会存储在客户端的硬盘中,24小时后就自动清除,如此可以提供更友好的服务。
我们继续创建一个验证页: prove.jsp,其代码如下:
- <body>
- <%
- Cookie cookies[] = request.getCookies();
- for(Cookie c:cookies)
- {
- if(c.getName().equals("username") || c.getName().equals("userpwd"))
- {
- out.println(c.getName()+":"+c.getValue());
- }
- }
- %>
- </body>
<body>
<%
Cookie cookies[] = request.getCookies();
for(Cookie c:cookies)
{
if(c.getName().equals("username") || c.getName().equals("userpwd"))
{
out.println(c.getName()+":"+c.getValue());
}
}
%>
</body>
在index.jsp页面中的用户名中填入:James,在密码中输入:admin,
此时页面显示结果为:
username:James userpwd:admin
事实上,在24小时内任意时间段输入http://jxpc-001:8080/ExtJs/request.jsp,那么网页最终都会显示为这样的结果。
5. session对象
对于session对象,我不打算多述,因为其作用基本与request相同,只是生命周期比request要长,从浏览器打开到关闭浏览器,如同一个单网页下设置了一个session范围属性和request范围属性,当页面关闭时,session范围属性我们可以不用forward跳转而在任何地方获得,其都不会丢失,而request范围属性,在关闭网页后,任何一个非forward跳转页中均获取不到,因为它的生命周期只在一次forward之间,断开这次forward,其属性会丢失掉。