JSP 脚本中的 9 个内置对象

JSP 脚本中包含了 9 个内置对象,这 9 个内置对象都是 Servlet API 接口的实例,只是 JSP 规范对它们进行了默认初始化。

 

这 9 个内置对象如下:

1、application:javax.servlet.ServletContext 的实例,该实例代表 JSP 所属的 Web 应用本身,可用于 JSP 页面,或者在 Servlet 之间交换信息。常用的方法有 getAttribute(String attrName)、setAttribute(String attrName, String attrValue) 和 getInitParameter(String paramName) 等。

2、config:javax.servlet.ServletConfig 的实例,该实例代表该 JSP 的配置信息。常用的方法有 getInitParameter(String paramName) 和 getInitParameternames() 方法。

3、exception:java.lang.Throwable 的实例,该实例代表其他页面中的异常和错误。只有当页面是错误页面,即编译指令 page 的 isErrorPage

 属性为 true 时,该对象才可以使用。常用的方法有 getMessage() 和 printStackTrace()。

4、out:javax.servlet.jsp.JspWriter 的实例,该实例代表 JSP 页面的输出流,用于输出内容,形成 HTML 页面。

5、page:代表该页面本身,通常没有太大用处。也就是 Servlet 中的 this,其类型就是生成的 Servlet 类,能用 page 的地方就可用 this。

6、pageContext:javax.servlet.jsp.PageContext 的实例,该对象代表该 JSP 页面上下文,使用该对象可以访问页面中的共享数据。常用的方法有 getServletContext() 和 getServletConfig() 。

7、request:javax.servlet.jsp.HttpServletRequest 的实例,该对象封装了一次请求,客户端的请求参数都被封装在该对象里。这是一个常用的对象,获取客户端请求参数必须使用该对象。常用的方法有 getParameter(String paramName)、getParameterValues(String paramName)、setAttribute(String attrName, Object attrValue)、getAttribute(String attrName) 和 setCharacterEncoding(String encoding)

8、response:javax.servlet.jsp.HttpServletResponse 的实例,代表服务器对客户端的响应。通常很少直接使用该对象,而是使用 out 对象,常用的方法有 getOutputStream()、setRedirect(String location)

9、session:javax.servlet.http.HttpSession 的实例,该对象代表一次会话。常用的方法有 getAttribute(String attrName)、setAttribute(String attrName, Object attrValue)

 

打开 jsp 生成的 servlet 文件,我们可以看到内置对象的声明及初始化:

final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    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;

  

try {
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;
}

  

上面的声明及定义位于 jspService 方法内

 

 

application 对象

通常有如下两个作用:

1、让多个 JSP 、Servlet 共享数据

application 通过 setAttribute(String attrName, Object value) 方法讲一个值设置成 application 的 attrName 属性,该属性的值对整个 Web 应用有效,因此该 web 应用的每个 JSP 页面或 Servlet 都可以访问该属性,访问属性的方法为 getAttribute(String attrName)。

 

application 不仅可以用于两个 JSP 页面之间共享数据,还可以用于 Servlet 和 JSP 之间共享数据。可以把 application 理解成一个 Map 对象,任何 JSP、Servlet 都可以把某个变量放入 application 中保存,并为之指定一个变量名;而该应用里的其他 Servlet、JSP 就可以根据该属性名来得到这个变量。

 

2、获得 web 应用配置参数

application 还有一个重要用处,可用于获得 web 应用的配置参数。如下:参数都在 web.xml 中配置了。

如下,在 web.xml 里面设置参数配置(context-param 标签):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">

<servlet>
    <servlet-name>get-application</servlet-name>
    <servlet-class>com.baiguiren.GetApplication</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>get-application</servlet-name>
    <url-pattern>/get-application</url-pattern>
</servlet-mapping>

<!-- 配置第一个参数:driver -->
<context-param>
  <param-name>driver</param-name>
  <param-value>com.mysql.jdbc.Driver</param-value>
</context-param>

<!-- 配置第二个参数:url -->
<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/jsp</param-value>
</context-param>

<!-- 配置第三个参数:user -->
<context-param>
  <param-name>user</param-name>
  <param-value>root</param-value>
</context-param>

<!-- 配置第四个参数:pass -->
<context-param>
  <param-name>pass</param-name>
  <param-value>root</param-value>
</context-param>

<welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

  

在 JSP 中获取参数:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.sql.*" %>

<html>
    <head>
        <title>通过application获取web.xml中的参数</title>
    </head>
    <body>
<%
// 从配置中获取参数
String driver = application.getInitParameter("driver");
// 从配置参数中获取数据库 url
String url = application.getInitParameter("url");
// 从配置参数中获取用户名
String user = application.getInitParameter("user");
// 从配置参数中获取密码
String pass = application.getInitParameter("pass");

// 注册驱动
Class.forName(driver);
// 获取数据库连接
Connection connection = DriverManager.getConnection(url, user, pass);
// 创建 Statement 对象
Statement stmt = connection.createStatement();
// 执行查询
ResultSet rs = stmt.executeQuery("select * from person");
%>

// 输出
<table bgcolor="#9999dd" border="1" width="480">
<%
// 遍历结果集
while(rs.next())
{
%>
<tr>
    <td><%=rs.getString(1)%></td>
    <td><%=rs.getString(2)%></td>
    <td><%=rs.getString(3)%></td>
</tr>
<%
}
%>
</table>
    </body>
</html>

  

 

 config 对象:

config对象代表当前 JSP 配置信息,但 JSP 通常无需配置,因此也就不存在配置信息。所以 JSP 页面比较少用该对象。

但在 Servlet 中则用处较大,因为 Servlet 需要在 web.xml 文件中进行配置,可以指定配置参数。

如:

web.xml 里面配置:

<servlet>
  <!-- 指定Servlet名字 -->
  <servlet-name>config</servlet-name>
  <!-- 指定将哪个 JSP 页面配置成Servlet -->
  <jsp-file>/config.jsp</jsp-file>
  <!-- 配置名为 name 的参数,值为 ruby -->
  <init-param>
    <param-name>name</param-name>
    <param-value>ruby</param-value>
  </init-param>
  <!-- 配置名为 age 的参数,值为 24 -->
  <init-param>
    <param-name>age</param-name>
    <param-value>24</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <!-- 指定将 config Servlet 配置到 /config 路径 -->
  <servlet-name>config</servlet-name>
  <url-pattern>/config</url-pattern>
</servlet-mapping>

  

jsp 文件:

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>config内置对象</title>
    </head>
    <body>
        <!-- 输出该 JSP 名为 name 的配置参数 -->
        name 配置参数的值为:<%=config.getInitParameter("name")%>
        <!-- 输出该 JSP 名为 age 的配置参数 -->
        age 配置参数的值为:<%=config.getInitParameter("age")%>
    </body>
</html>

  

 

exception 对象

exception 对象是 Throwable 的实例,代表 JSP 脚本中产生的错误和异常,是 JSP 页面异常机制的一部分。

JSP 中的异常都可交给错误处理页面处理。

如:

首先需要在其他出现异常的页面的 page 指令中指定 errorPage 是下面的页面:

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="error.jsp" %>

 

又或者在 web.xml 中配置如下内容:

error-page>
   <exception-type>java.lang.Throwable</exception-type>
   <location>/error.jsp</location>
 </error-page>

 

error.jsp

<%@ page contentType="text/html; charset=UTF-8" isErrorPage="true" %>

<html>
    <head>
        <title>error</title>
        <link href="assets/prism/prism.css" rel="stylesheet" />
    </head>

    <body>
        异常类型:<pre><code class="language-java"></code><%=exception.getClass()%></code></pre><br/>
        异常信息:<pre><code class="language-java"><%=exception.getMessage()%></code></pre><br/>
        错误堆栈:<pre><code class="language-java"></code><%=exception.getStackTrace()%></code></pre><br/>


        <script src="assets/prism/prism.js"></script>
    </body>
</html>

  

 

out 对象:

out 对象代表一个页面输出流,通常用于在页面上输出变量值及常量。一般在使用输出表达式的地方,都可以用 out 对象来达到同样效果。

如:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.sql.*" %>

<html>
    <head>
        <title>out 测试</title>
    </head>
    <body>
<%
// 注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsp", "root", "root");
// 创建 Statement 对象
Statement stmt = conn.createStatement();
// 执行查询,获得 ResultSet 对象
ResultSet rs = stmt.executeQuery("select * from person");
%>
        <table border="1" width="400">
            <%
            // 遍历结果集
            while(rs.next()) {
                // 输出表格行
                out.println("<tr>");
                // 输出表格列
                out.println("<td>");
                // 输出结果集第一列的值
                out.println(rs.getString(1));
                // 关闭表格列
                out.println("</td>");
                // 开始表格列
                out.println("<td>");
                // 输出结果集第二列的值
                out.println(rs.getString(2));
                // 关闭表格列
                out.println("</td>");
                // 关闭表格行
                out.println("</tr>");
            }
            %>
        </table>
    </body>
</html>

所有使用 out 的地方,都可使用输出表达式来代替,而且使用输出表达式更加简洁。

 

我们把上面的写法换成输出表达式:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.sql.*" %>

<html>
    <head>
        <title>out 测试</title>
    </head>
    <body>
<%
// 注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsp", "root", "root");
// 创建 Statement 对象
Statement stmt = conn.createStatement();
// 执行查询,获得 ResultSet 对象
ResultSet rs = stmt.executeQuery("select * from person");
%>
        <table border="1" width="400">
            <%
            // 遍历结果集
            while(rs.next()) {
            %>
            <tr>
                <td><%=rs.getString(1)%></td>
                <td><%=rs.getString(2)%></td>
            </tr>
            <%
            }
            %>
        </table>
    </body>
</html>

我们可以明显看到,输出结果集的代码量更少了,并且结构也更加的清晰。

 

 

pageContext 对象

这个对象代表页面上下文,该对象主要用于访问 JSP 之间的共享数据。使用 pageContext 可以访问 page、request、session、application 范围的变量。

pageContext 是 PageContext 类的实例,它提供了如下两个方法来访问 page、request、session、application 范围的变量。

1、getAttribute(String name):取得 page 范围内的 name 属性。

2、getAttribute(String name, int scope):取得指定范围内的 name 属性,其中 scope 可以是如下 4 个值。

 PageContext.PAGE_SCOPE:对应于 page 范围

 PageContext.REQUEST_SCOPE:对应于 request 范围

 PageContext.SESSION_SCOPE:对应于 session 范围

 PageContext.APPLICATION_SCOPE:对应于 application 范围

 

与 getAttribute() 方法对应,PageContext 也提供了两个对应的 setAttribute() 方法,用于将指定变量放入 page、request、session、application 范围内。

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>pageContext</title>
    </head>
    <body>
<%
// 使用 pageContext 设置属性,该属性默认在 page 范围内
pageContext.setAttribute("page", "hello");
// 使用 request 设置属性,该属性默认在 request 范围内
request.setAttribute("request", "hello");
// 使用 pageContext 将属性设置在 request 范围内
pageContext.setAttribute("request2", "hello", pageContext.REQUEST_SCOPE);
// 使用 session 将属性设置在 session 范围内
session.setAttribute("session", "hello");
// 使用 pageContext 将属性设置在 session 范围内
pageContext.setAttribute("session2", "hello", pageContext.SESSION_SCOPE);
// 使用 application 将属性设置在 application 范围内
application.setAttribute("application", "hello");
// 使用 pageContext 将属性设置在 application 范围内
pageContext.setAttribute("application2", "hello", pageContext.APPLICATION_SCOPE);
%>
        <h3>获取各属性的值</h3>
        <p>page 范围的 page 属性值:<%=pageContext.getAttribute("page")%></p>
        <p>request  范围的 request 属性值:<%=request.getAttribute("request")%></p>
        <p>request  范围的 request2 属性值:<%=request.getAttribute("request2")%></p>
        <p>session 范围的 session 属性值:<%=session.getAttribute("session")%></p>
        <p>session 范围的 session2 属性值:<%=session.getAttribute("session2")%></p>
        <p>application 范围的 application 属性值:<%=application.getAttribute("application")%></p>
        <p>application 范围的 application2 属性值:<%=application.getAttribute("application2")%></p>
    </body>
</html>

  

 

request 对象:

request 对象是 JSP 中重要的对象,每个 request 对象封装着一次用户请求,并且所有的请求参数都被封装在 request 对象中,因此 request 对象是获取请求参数的重要途径。

1、获取请求头/请求参数

String getParameter(String paramName):获取 paramName 请求参数的值。

Map getParameterMap(): 获取所有请求参数名和参数值组成的 Map 对象。

Enumeration getParameterNames():获取所有请求参数名所组成的 Enumeration 对象。

String[] getParameterValues(String name):name 请求参数的值,当该请求参数有多个值时,该方法将返回多个值所组成的数组。

 

HttpServletRequest 提供了如下方法来访问请求头:

String getHeader(String name):获取指定请求头的值。

java.util.Enumeration<String> getHeaderNames():获取所欲请求头的名称。

java.util.Enumeration<String> getHeaders(String name):获取指定请求头的多个值。

int getIntHeader(String name):获取指定请求头的值,并将该值转为整数值。

 

并不是每个表单域都会生成请求参数,而是有 name 属性的表单域才生成请求参数。关于表单域和请求参数的关系遵循如下四点:

a、每个有 name 属性的表单域对应一个请求参数。

b、如果多个表单域有相同的 name 属性,则多个表单域只生成一个请求参数,只是该参数有多个值。

c、表单域的 name 属性指定请求参数名,value 指定请求参数值。

d、如果某个表单域设置了 disabled="disabled" 属性,则该表单域不再生成请求参数。

 

request示例:

form.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>form</title>
    </head>
    <body>
        <form method="POST" action="request1.jsp">
            用户名:<br /><input type="text" name="name"><hr/>

            性别:<br />
            男:<input type="radio" name="gender" value="男">
            女:<input type="radio" name="gender" value="女"><hr/>

            喜欢的颜色:<br />
            红:<input type="checkbox" name="color" value="红">
            蓝:<input type="checkbox" name="color" value="蓝">
            绿:<input type="checkbox" name="color" value="绿"><hr/>

            来自的国家:<br />
            <select name="country">
                <option value="中国">中国</option>
                <option value="美国">美国</option>
                <option value="俄罗斯">俄罗斯</option>
            </select><hr/>

            <input type="submit" value="提交">
            <input type="reset" value="重置">
        </form>
    </body>
</html>

  

request1.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>

<html>
    <head>
        <title>获取请求头/请求参数</title>
    </head>
    <body>
<%
// 获取所有请求头的名称
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements())
{
    String headerName = headerNames.nextElement();
    // 获取每个请求、及其对应的值
    out.println(headerName + "-->" + request.getHeader(headerName) + "<br />");
}
out.println("<hr/>");

// 设置解码方式
request.setCharacterEncoding("UTF-8");
// 下面依次获取表单域的值
String name = request.getParameter("name");
String gender = request.getParameter("gender");
// 如果某个请求参数有多个值,将使用该方法获取多个值
String[] colors = request.getParameterValues("color");
String nation1 = request.getParameter("country");
%>

    <!-- 下面依次输出表单域的值 -->
    你的名字:<%=name%><hr/>
    你的性别:<%=gender%><hr/>
    <!-- 输出复选框获取的数组值 -->
    你喜欢的颜色:<% for(String c: colors)
    out.println(c + " ");%><hr/>
    你来自的国家:<%=nation1%><hr/>
    </body>
</html>

  

获取包含非西欧字符的 GET 请求参数:

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>request2</title>
    </head>
    <body>
<%
// 获取请求里包含的查询字符串
String rawQueryStr = request.getQueryString();
out.println("原始查询字符串为:" + rawQueryStr + "<hr/>");
// 使用 URLDecoder 解码字符串
String queryStr = java.net.URLDecoder.decode(rawQueryStr, "UTF-8");
out.println("解码后的查询字符串为:" + queryStr + "<hr/>");
// 以 & 号分解查询字符串
String[] parameterPairs = queryStr.split("&");
for(String parameterPair : parameterPairs)
{
    out.println("每个请求参数名、值为:" + parameterPair + "<br />");
    // 以 = 来分解请求参数名和值
    String[] nameValue = parameterPair.split("=");
    out.println(nameValue[0] + "参数的值是:" + nameValue[1] + "<hr>");
}
%>
    </body>
</html>

  

也可以在获取请求参数之后对请求参数值重新编码,也就是先将其转换成字节数组,再将字节数组重新解码成字符串。如:

// 获取原始的请求参数值
String rawName = request.getParameter("name");
// 将请求参数值使用 ISO-8859-1 字符串分解成字节数组
byte[] rawBytes = rawName.getBytes("ISO-8859-1");
// 将字节数组重新解码成字符串
String name = new String(rawBytes, "UTF-8");

  

 

2、操作 request 范围的属性

HttpServletRequest 还包含如下两个方法,用于设置和获取 request 范围的属性。

setAttribute(String attrName, Object attrValue):将 attrValue 设置成 request 范围的属性。

Object getAttribute(String attrName):获取 request 范围属性。

当 forward 用户请求时,请求的参数和请求属性都不会丢失。

 

3、执行 forward 或 include

request 还有一个功能就是执行 forward 和 include,也就是代替 JSP 所提供的 forward 和 include 动作指令。前面需要 forward 时都是使用 JSP 的 forward 指令,实际上 request 对象也可以执行 forward。

HttpServletRequest 类提供了一个 getRequestDispatcher(String path) 方法,其中 path 就是希望 forward 或者 include 的目标路径,该方法返回 RequestDispatcher,该对象提供了如下两个方法:

a、forward(ServletRequest request, ServletResponse response):执行 forward。

b、include(ServletRequest request, ServletResponse response):执行 include。

 

如下代码可以将 a.jsp 页面 include 到本页面中:

request.getRequestDispatcher("/a.jsp").forward(request, response);

如下代码可以将请求 forward 到 a.jsp 页面:

request.getRequestDispatcher("/a,jsp").forward(request, response);

注意:使用 request 的 getRequestDispatcher(String path) 方法时,该 path 字符串必须以斜线开头。

 

 

response 对象:

response 代表服务器对客户端的响应。大部分时候,程序无须使用 response 来响应客户端请求,因为有个更简单的响应对象 -- out,它代表页面输出流,直接使用 out 生成响应更简单。

但 out 是 JspWriter 的实例,JspWriter 是 Writer 的子类,Writer 是字符流,无法输出非字符内容,假如需要在页面中动态生成一副位图、或者输出一个 PDF 文档,使用 out 作为响应对象将无法完成,此时必须使用 response 作为响应输出。

 

1、response 响应生成非字符响应

对于需要生成非字符响应的情况,就应该使用 response 来响应客户端请求。下面的 JSP 页面将在客户端生成一张图片。response 是 HttpServletResponse 接口的实例,该接口提供了一个 getOutputStream() 方法,该方法返回响应输出字节流。

如下,输出一张图片:

img.jsp

<!-- 通过 contentType 指定响应数据是图片 -->
<%@ page contentType="image/png" %>
<%@ page import="java.awt.image.*,javax.imageio.*,java.io.*,java.awt.*" %>

<%
// 创建 BufferedImage 对象
BufferedImage image = new BufferedImage(340, 160, BufferedImage.TYPE_INT_RGB);
// 以 Image 对象获取 Graphics 对象
Graphics g = image.getGraphics();
// 使用 Graphics 画图,所画的图将会出现在 image 对象中
g.fillRect(0, 0, 400, 400);
// 设置颜色:红
g.setColor(new Color(255, 0, 0));
// 画出一段弧
g.fillArc(20, 20, 100, 100, 30, 120);
// 设置颜色:绿
g.setColor(new Color(0, 255, 0));
// 画出一段弧
g.fillArc(20, 20, 100, 100, 150, 120);
// 设置颜色:蓝
g.setColor(new Color(0, 0, 255));
// 画出一段弧
g.fillArc(20, 20, 100, 100, 270, 120);
// 设置颜色:黑
g.setColor(new Color(0, 0, 0));
g.setFont(new Font("Arial Black", Font.PLAIN, 16));
// 画出三个字符串
g.drawString("red:climb", 200, 60);
g.drawString("green:swim", 200, 100);
g.drawString("blue:jump", 200, 140);
g.dispose();
// 将图像输出到页面响应
ImageIO.write(image, "png", response.getOutputStream());
%>

  

使用方法 <img src="/img.jsp">

 

以上页面的 contentType 指定为 image/png,这表明服务器响应是一张 PNG 图片。接着创建了一个 BufferedImage 对象(代表图像),并获取该 BufferedImage 的 Graphics 对象(代表画笔),然后通过 Graphics 向 BufferedImage 中绘制图形,最后一行代码直接将 BufferedImage 作为响应发送给客户端。

 

2、重定向

重定向是 response 的另外一个用处,与 forward 不同的是,重定向会丢失所有的请求参数和 request 范围属性,因为重定向将生成第二次请求,与前一次请求不在同一个 request 范围内,所以发送一次清的请求参数和 request 范围属性都会丢失。

 

HttpServletResponse 提供了一个 sendRedirect(String path) 方法,该方法用于重定向到 path 资源,即重新向 path 资源发送请求。

如:

redirect.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<%
// 生成页面响应
out.println("====");
// 重定向到 redirect-result.jsp 页面
response.sendRedirect("redirect-result.jsp");
%>

  

redirect-result.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>redirect result</title>
    </head>
    <body>
        被重定向的页面<br/>
        name 请求参数的值: <%=request.getParameter("name")%>
    </body>
</html>

  

我们在第一个页面的链接后面加上一个get请求参数:http://localhost:8080/jsp/redirect.jsp?name=awk,然后我们在重定向的页面会发现获取到的参数却是 null。

这就说明,我们的 request 里面的参数已经丢失了。

 

forward 与 redirect 的三个区别:

a、执行 forward 后依然是上一次请求,执行 redirect 后生成第二次请求

b、forward 的目标页面可以访问原请求的参数,因为依然是同一次请求,所有原请求的请求参数、request 范围属性全部存在。redirect 的目标页面不能访问原请求的请求参数、request 范围属性,因为 redirect 产生了一个新的请求。

c、forward 的时候地址栏 URL 不会发生变化。redirect 的时候地址栏 URL 是 redirect 的时候 sendRedirect 参数的值。

 

3、增加 Cookie

 response 对象提供了如下方法:

void addCookie(Cookie cookie):增加cookie

增加 cookie 请按如下步骤进行。

a、创建 Cookie 实例,Cookie 的构造器为 Cookie(String name, String value)

b、设置 Cookie 的生命期限,即该 Cookie 在多长时间内有效。

c、向客户端写 Cookie

 

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>cookie</title>
    </head>
    <body>
<%
// 获取请求参数
String name = request.getParameter("name");
// 以获取到的请求参数为值,创建一个 Cookie 对象
Cookie c = new Cookie("username", name);
// 设置 Cookie 对象的生存期限(这里是 24 小时)
c.setMaxAge(24 * 3600);
// 向客户端增加 Cookie 对象
response.addCookie(c);
%>
    </body>
</html>

  

访问客户端的 cookie,request 对象提供了 getCookies 方法,该方法返回客户端机器上所有 Cookie 组成的数组。

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>读取 cookie</title>
    </head>
    <body>
<%
// 获取本站在客户端上保留的所有 cookie
Cookie[] cookies = request.getCookies();
// 遍历客户端上的每个 Cookie
for (Cookie c : cookies) {
    // 如果 Cookie 的名为 username,表明该 Cookie 是需要访问的 Cookie
    if (c.getName().equals("username")) {
        out.println(c.getValue());
    }
}
%>
    </body>
</html>

  

默认情况下,Cookie 值不允许出现中文字符,如果需要值为中文内容的 Cookie,我们可以借助于 java.net.URLEncoder 先对中文字符串进行编码,将编码后的结果设置为 Cookie 值。当程序要读取 Cookie 时,则应该先读取,然后使用 java.net.URLDecoder 对其进行解码。

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>中文 Cookie</title>
    </head>
    <body>
<%
// 以编码后的字符串为值,创建一个 Cookie 对象
Cookie c = new Cookie("cnName", java.net.URLEncoder.encode("李白", "utf-8"));
// 设置 Cookie 对象的生存期限
c.setMaxAge(24 * 3600);
// 向客户端增加 Cookie 对象
response.addCookie(c);

// 获取本站在客户端上保留的所有 Cookie
Cookie[] cookies = request.getCookies();
// 遍历客户端上的每个 Cookie
for (Cookie cookie : cookies) {
    // 如果 Cookie 的名为 cnName,表明该 Cookie 是需要访问的 Cookie
    if (cookie.getName().equals("cnName")) {
        // 使用 java.net.URLDecoder 对 Cookie 值进行解码
        out.println(java.net.URLDecoder.decode(cookie.getValue()));
    }
}
%>
    </body>
</html>

  

 

 

session 对象

session 对象代表一次用户会话。一次用户会话的含义是:从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开为止,这个过程就是一次会话。

session 范围内的属性可以在多个页面的跳转之间共享。一旦关闭浏览器,即 session 结束,session 范围内的属性将全部丢失。

 

session 对象是 HttpSession 的实例,HttpSession 有如下两个常用的方法。

setAttribute(String attrName, Object attrValue):设置 session 范围内 attrName 属性的值为 attrValue。

getAttribute(String attrName):返回 session 范围内 attrName 属性的值。

 

使用 session 示例:

shop.jsp

<%@ page contentType="text/html; charset=UTF-8" %>

<html>
    <head>
        <title>选择物品购买</title>
    </head>
    <body>
        <form method="POST" action="process-buy.jsp">
            书籍:<input type="checkbox" name="item" value="book"/><br/>
            电脑:<input type="checkbox" name="item" value="computer"/><br/>
            汽车:<input type="checkbox" name="item" value="car"/><br/>
            <input type="submit" value="购买" />
        </form>
    </body>
</html>

  

process-buy.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>

<%
// 取出 session 范围的 itemMap 属性
Map<String, Integer> itemMap = (Map<String, Integer>)session.getAttribute("itemMap");
// 如果 Map 对象为空,则初始化 Map 对象
if (itemMap == null)
{
    itemMap = new HashMap<String, Integer>();
    itemMap.put("书籍", 0);
    itemMap.put("电脑", 0);
    itemMap.put("汽车", 0);
}
// 获取上一个页面的请求参数
String[] buys = request.getParameterValues("item");
// 遍历数组的各元素
for (String item : buys)
{
    // 如果 item 为 book,表示选择购买书籍
    if (item.equals("book"))
    {
        int num1 = itemMap.get("书籍").intValue();
        // 将书籍 key 对应的数量加 1
        itemMap.put("书籍", num1 + 1);
    }
    else if (item.equals("computer"))
    {
        int num2 = itemMap.get("电脑").intValue();
        itemMap.put("电脑", num2 + 1);
    }
    else if (item.equals("car"))
    {
        int num3 = itemMap.get("汽车").intValue();
        itemMap.put("汽车", num3 + 1);
    }
}

// 将 itemMap 对象放到 session 范围中
session.setAttribute("itemMap", itemMap);
%>

<html>
    <head>
        <title>process buy</title>
    </head>
    <body>
        你购买的物品:<br/>
        书籍:<%=itemMap.get("书籍")%>本<br/>
        电脑:<%=itemMap.get("电脑")%>台<br/>
        汽车:<%=itemMap.get("汽车")%>辆<br/>
        <p><a href="shop.jsp">再次购买</a></p>
    </body>
</html>

  

关于 session 还有一点需要注意的,session 保存的信息需要保存到 web 服务器的硬盘上,所以要求 session 里的属性值必须是可序列化的,否则将会引发不可序列化的异常。

session 的属性值可以是任何可序列化的 Java 对象。

 

posted @ 2018-03-20 22:23  佚名000  阅读(328)  评论(0编辑  收藏  举报