Prism代码语法高亮

第6章 JSP技术


学习目标

在动态网页开发中,经常需要动态生成HTML内容,例如,一篇新闻报道的浏览次数需要动态生成。如果使用Servlet实现HTML页面数据的生成,需要调用大量的Servlet输出语句,使静态内容和动态内容混合在一起,导致程序非常臃肿。为了克服Servlet的这些缺点,Oracle(Sun)公司推出了JSP技术。

1. JSP概述

1.1 什么是JSP

(1) JSP的概念

JSP全名是Java Server Pages,即Java服务器页面,它是Servlet更高级别的扩展。

JSP = HTML + Java脚本

最终,JSP文件会通过Web服务器的Web容器编译成一个Servlet,用来处理各种请求。

(2) JSP的特征

1.2 编写第一个JSP文件

参照ch04创建ch06-jxp项目,创建ch06首页index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <meta charset="UTF-8">
    <title>ch06 JSP技术(张晓轩)</title>
  </head>
  <body>
  <h1>ch06 JSP技术(张晓轩)</h1>
  <hr>
  <a href="01helloworld_zxx.jsp">1. 我的第1个JSP网页</a><br>
  <a href="02timeInfo_zxx.jsp">2. JSP页面的基本构成--显示当前时间</a><br>
  <a href="03example01_zxx.jsp">3. JSP Scriptlets、声明变量、表达式</a><br>
  <a href="04example02_zxx.jsp">4. JSP声明语句</a><br>
  <a href="05example03_zxx.jsp">5. JSP注释、html注释</a><br>
  <a href="06example04_zxx.jsp">6. 动态注释</a><br>
  <a href="07include_zxx.jsp">7. 静态包含&lt; %@ include file="date.jsp"% &gt;</a><br>
  <a href="08dynamicInclude_zxx.jsp">8. 动态包含&lt;jsp:include page="included.jsp" flush="true" /&gt; </a><br>
  <a href="09jspforward_zxx.jsp">9. 转发forward </a><br>
  <a href="10out_zxx.jsp">10. out与response.getWriter()输出的区别 </a><br>
  <a href="10out2_zxx.jsp">10. out与response.getWriter()输出的区别 --- buffer="0kb" </a><br>
  <a href="11pageContext_zxx.jsp">11. pageContext.set|get|findAttribute 设置、提取、查找属性</a><br>
  <a href="12exception_zxx.jsp">12. 异常对象测试</a><br>
  <a href="13table_zxx.jsp">13. 应用Java程序片段动态生成表格</a><br>
  <a href="页面转发/forward_zxx.jsp">任务1. 页面转发</a><br>
  <a href="用户注册/user_register_zxx.jsp">任务2. 用户注册</a><br>
  <hr>
  <p><a href="http://101.42.158.247/21javaweb.html">返回课程首页</a>
  张晓轩 <script>document.write(document.lastModified); </script> 制作</p>
  </body>
</html>

运行结果如下:

图1 ch06 JSP技术--首页

01helloworld_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>My First JSP 张晓轩</title>
</head>
<body>
    <h1>My First JSP 张晓轩</h1>
</body>
</html>

运行结果显示如右:My First JSP 张晓轩

1.3 JSP运行原理

(1) 解读Tomcat 9.0.65\conf\web.xml

        <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

说明:*.jsp或.jspx由org.apache.jasper.servlet.JspServlet.java解析执行

(2) 解读jsp执行原理

图2 JSP的运行原理图
图3 JSP、java、class文件名的对应关系

01helloworld_zxx.jsp对应的Servlet文件_01helloworld_005fjxp_jsp.java

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.65
 * Generated at: 2022-09-22 16:15:16 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class _01helloworld_005fjxp_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    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;

      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("    <title>My First JSP 张晓轩</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("    <h1>My First JSP 张晓轩</h1>\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

2. JSP基本语法

2.1 JSP页面的基本构成

JSP页面 = Σ 指令标识(动)、HTML代码(静)、CSS代码(静)、JavaScript代码(静)、嵌入的Java代码(动)、JSP动作标识(动)、注释

JSP页面的基本构成

02timeInfo_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<html>
<head>
    <title>JSP页面---显示当前时间</title>
</head>
<body>
    <h1>JSP页面的基本构成(张晓轩)</h1>
    <p><mark>JSP页面 = Σ 指令标识(动)、HTML代码(静)、CSS代码(静)、JavaScript代码(静)、嵌入的Java代码(动)、注释JSP动作标识(动)、注释</mark></p>
    <hr>
    <%
        Date date = new Date();
        // 此处的当前时间时Web服务器端的当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
        String today =df.format(date);
    %>
    Web服务器端的当前时间:<%=today%>
    <hr>
    客户端浏览器的当前时间:

    <script>
        function getNowDate(){
            var nowdate = new Date();            //  客户端浏览器的当前时间
            var year = nowdate.getFullYear();    //  返回的是年份
            var month = nowdate.getMonth() + 1;  //  返回的月份上个月的月份,记得+1才是当月
            var dates = nowdate.getDate();       //  返回的是几号
            var day = nowdate.getDay();          //  周一返回的是1,周六是6,但是周日是0
            var week = [ "星期日","星期一","星期二","星期三","星期四","星期五","星期六"];
            var h = nowdate.getHours();
            var m = nowdate.getMinutes();
            var s = nowdate.getSeconds();
            month = checkTime(month);
            dates = checkTime(dates);
            h = checkTime(h);
            m = checkTime(m);
            s = checkTime(s);
            return year + "年" + month + "月" + dates + "日 " + week[day] + " " + h +":" + m + ":" + s;
        }

        var checkTime = function (i) {
            if (i < 10) {
                i = "0" + i;
            }
            return i;
        }

        document.write(getNowDate());
    </script>
</body>
</html>

运行结果:

图4 JSP页面的基本构成--当前时间

2.2 JSP脚本元素

需要注意的是,

03example01_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSP Scriptlets、声明变量、表达式</title>
</head>
<body>
    <h1>JSP Scriptlets、声明变量、表达式(张晓轩)</h1>
    <hr>
    JSP Scriptlets 执行的输出:
    <%
        int a = 1, b = 2; //定义两个变量a,b
        out.println(a+b);
    %>
    <hr>

    <%!
        int x = 3, y = 4; //定义两个变量x,y
        String 单位名称 = "信息工程学院";
    %>
    =表达式 执行的输出:<br>
    3+4=<%=x+y %><br>
    单位名称、用户名称 = <%=单位名称 + " 张晓轩"%><br>
</body>
</html>

运行结果:

图5 JSP Scriptlets、声明变量、表达式

04example02_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSP声明语句</title>
</head>
<body>
    <h1>JSP声明方法和调用方法(张晓轩)</h1>
    <%!
        public int add(int a, int b) { //定义add方法
            return a+b;
        }
    %>
    <hr>
    add(1,2)=<%
        out.println(add(1,2));//调用add()方法,输出其返回值
    %> <br>
    add(3,4)=<%
        out.println(add(3,4));
    %> <br>
    add(5,6)=<%
        out.println(add(5,6));
    %>
</body>
</html>

运行结果:

图6 JSP声明方法和调用方法

2.3 JSP注释

//注释内容 java代码的单行注释

/*
  java代码的多行注释1
  java代码的多行注释2
  ......
*/

/*
 * java代码的多行美观注释1
 * java代码的多行美观注释2
 * ......
 */

/**
  提示信息1 能被Javadoc文档工具生成文档时提取的注释
  提示信息2
  ......
 */

/**
 * 美观提示信息1 能被Javadoc文档工具生成文档时提取的注释
 * 美观提示信息2
 * ......
 */

<%-- 隐藏注释 生成的html源代码不显示 --%>

<!-- HTML注释 html源代码显示 -->

05example03_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>JSP注释</title>
</head>
<body>
    <h2>JSP注释(浏览器中查看源代码)</h2>
    <!-- 这个是HTML注释 -->
    <%-- 这个是JSP注释 --%>
</body>
</html>

06example04_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>动态注释</title>
</head>
<body>
    <h2>动态注释(浏览器中查看源代码)</h2>
    <!-- 动态注释 <%=new Date()%> -->
</body>
</html>

3. JSP指令

3.1 page指令

<%@ page 属性名1= "属性值1" 属性名2= "属性值2" ...%>

page指令的常用属性

属性名称 取值范围 描述
language java 指定JSP页面所用的脚本语言,默认为Java,可缺省
import 任何包名、类名 指定在JSP页面翻译成的Servlet源文件中导入的包或类。import是唯一可以声明多次的page指令属性。一个import属性可以引用多个类,中间用英文逗号隔开。需要注意的是,JSP 容器自动导入以下4个包
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
session true、false 指定该JSP内是否内置Session对象,如果为true,则说明内置Session对象,可以直接使用,否则没有内置Session对象。默认情况下,session属性的值为true
isErrorPage true、false 指定该页面是否为错误处理页面,如果为true,则该JSP内置有一个Exception对象的exception,可直接使用。默认情况下,isErrorPage的值为false
errorPage 某个JSP页面的相对路径 指定一个错误页面,如果该JSP程序抛出一个未捕捉的异常,则转到errorPage指定的页面。errorPage指定页面的isErrorPage属性为true,且内置的exception对象为未捕捉的异常
contentType 有效的文档类型 指定当前JSP页面的MIME类型和字符编码,例如:
HTML格式为text/html
纯文本格式为text/plain
JPG图像为image/jpeg
GIF图像为image/gif
Word文档为application/msword
pageEnCoding 当前页面 指定页面编码格式


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

需要注意的是,page指令对整个页面都有效,而与其书写的位置无关,但是习惯上把page指令写在JSP页面的最前面。

3.2 include指令(静态包含)

<%@ include file="被包含的文件地址"%>

需要注意的是,插入文件的路径一般不以“/”开头,而是使用相对路径

07date.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<html>
<head>
    <title>date</title>
</head>
<body>
    当前时间是:
    <%
        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
        String today =df.format(date);
        out.println(today);
    %>
</body>
</html>

07include_zxx.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
    <title>静态包含</title>
</head>
<body>
    <h1>静态包含:&lt;%@ include file="相对路径资源"%></h1>
    <hr>
    <p>静态包含:把要被包含的文件(如07date.jsp)插入包含文件(如本文件)中编译、执行。</p>
    <%@ include file="07date.jsp"%>
    <p>include file="07date.jsp" 执行之后的段落。</p>
</body>
</html>

运行结果:

图7 静态包含指令<%@ include file="07date.jsp"%>

使用include指令的常见问题

3.3 taglib指令 (下章jstl会讲到)

在JSP文件中,可以通过taglib指令标识该页面中所使用的标签库,同时引用标签库,并指定标签的前缀。

<%@ taglib prefix="tagPrefix" uri="tagURI" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

4. JSP动作元素

4.1 动态包含文件元素<jsp:include>

在JSP页面中,<jsp:include>动作元素用于向当前页面引入其他的文件,被引入的文件可以是动态文件,也可以是静态文件。

<jsp:include page="URL" flush="true|false" />

include指令与<jsp:include>动作元素的区别

08included.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>include</title>
</head>
<body>
    <%Thread.sleep(5000);%>
    included.jsp内的中文<br>
</body>
</html>

08dynamicInclude_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>dynamicInclude page</title>
</head>
<body>
    <h1>动态包含&lt;jsp:include page="08included.jsp>"</h1>
    <hr>
    dynamicInclude.jsp内的中文
    <br />
    <jsp:include page="08included.jsp" flush="true" />
</body>
</html>

运行结果:

图8 动态包含文件元素<jsp:include>

4.2 请求转发元素<jsp:forward>

<jsp:forward>动作元素可以将当前请求转发到其他Web资源(HTML页面、JSP页面和Servlet等),执行请求转发之后,当前页面将不再执行,而是执行该元素指定的目标页面。

<jsp:forward page="relativeURL" />

page属性用于指定请求转发到的资源的相对路径,该路径的目标文件必须是当前应用中的内部资源

09welcome.jsp

<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>欢迎进入首页</title>
</head>
<body>
    你好,欢迎进入首页,当前访问时间是:
    <%
        SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
        out.print(df.format(new java.util.Date()));
    %>
</body>
</html>

09jspforward_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>forword page</title>
</head>
<body>
    <!--运行是再控制台能看到【转发之前】,看不到【转发之后】-->
    <%
        System.out.println("转发之前");
    %>
    <jsp:forward page="09welcome.jsp" />
    <%
        System.out.println("转发之后");
    %>
</body>
</html>

运行结果:

图9 请求转发元素<jsp:forward>

5. JSP隐式对象

5.1 隐式对象的概述

JSP中的9个隐式对象

名称 类型 描述
out javax.servlet.jspJspWriter 用于页面输出
request javax.servlet.http.HttpServletRequest 得到用户请求信息
response javax.servlet.http.HttpServletResponse 服务器向客户端的回应信息
config javax.servlet.ServletConfig 服务器配置,可以取得初始化参数
session javax.servlet.http.HttpSession 用来保存用户的信息
application javax.servlet.ServletContext 所有用户的共享信息
page java.lang.Object 指当前页面转换后的Servlet类的实例
pageContext javax.servlet.jsp.PageContext JSP的页面容器
exception java.lang.Throwable 表示JSP页面所发生的异常,在错误页中才起作用

5.2 out对象

在JSP页面中使用out对象向客户端发送文本内容。out对象是javax.servlet.jsp.JspWriter类的实例对象,它的作用与ServletResponse.getWriter()方法返回的PrintWriter对象非常相似,都是用来向客户端发送文本形式的实体内容。不同的是,out对象的类型为JspWriter,它相当于带缓存功能的PrintWriter。

图10 out对象与Servlet引擎提供的缓冲区之间的工作关系图

10out_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>out与response.getWriter()输出的区别</title>
</head>
<body>
    <h1>out与response.getWriter()输出的区别(张晓轩)</h1>
    <hr>
    <%
        out.println("第1行 first line。out输出。<br>");
        response.getWriter().println("第2行 second line。response.getWriter()输出<br>");
    %>
</body>
</html>
图11 out与response.getWriter()输出的区别

10out2_zxx.jsp 和上述代码区别:仅首行多 buffer="0kb"

<%@ page contentType="text/html;charset=UTF-8" language="java" buffer="0kb" %>
<html>
<head>
    <title>out与response.getWriter()输出的区别</title>
</head>
<body>
    <h1>out与response.getWriter()输出的区别(张晓轩) --- buffer="0kb" </h1>
    <hr>
    <%
        out.println("第1行 first line。out输出。<br>");
        response.getWriter().println("第2行 second line。response.getWriter()输出<br>");
    %>
</body>
</html>

运行结果:

图12 out与response.getWriter()输出的区别--- buffer="0kb"

5.3 pageContext对象

在JSP页面中,使用pageContext对象可以获取JSP的其他8个隐式对象。pageContext对象是javax.servlet.jsp.PageContext类的实例对象,它代表当前JSP页面的运行环境,并提供了一系列用于获取其他隐式对象的方法。

(1) pageContext对象获取其他8个隐式对象的方法

方法名 功能描述
JspWriter getOut() 用于获取out隐式对象
Object getPage() 用于获取page隐式对象
ServletRequest getRequest() 用于获取request隐式对象
ServletResponse getResponse() 用于获取response隐式对象
HttpSession getSession() 用于获取session隐式对象
Exception getException() 用于获取exception隐式对象
ServletConfig getServletConfig() 用于获取config隐式对象
ServletContext getServletContext() 用于获取application隐式对象

(2) pageContext操作属性的相关方法

方法名 功能描述
void setAttribute(String name,Object value,int scope) 用于设置pageContext对象的属性
Object getAttribute(String name,int scope) 用于获取pageContext对象的属性
void removeAttribute(String name,int scope) 用于删除指定范围内名称为name的属性
void removeAttribute(String name) 用于删除所有范围内名称为name的属性
Object findAttribute(String name) 用于从4个域对象中查找名称为name的属性

(3) pageContext对象的作用范围

pageContext操作属性的相关方法中参数name指定的是属性名称,参数scope指定的是属性的作用范围。pageContext对象的作用范围有4个值,具体如下:

上述4个范围的顺序,时间角度从短到长的顺序:当前页面 -> 本次请求 -> 本次会话 -> 本应用程序;空间角度从小到大的顺序:当前页面 -> 本次请求所涉及的JSP页面或Servlet -> 本次会话所涉及的JSP页面或Servlet -> 本应用程序所涉及的JSP页面或Servlet。

需要注意的是,当调用findAttribute()方法查找名称为name的属性时,会按照page、request、session和application的顺序依次进行查找,如果找到,则返回属性的名称,否则返回null。

11pageContext_zxx.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
    <title>pageContext</title>
</head>
<body>
<h1>pageContext.set|get|findAttribute 设置、提取、查找属性</h1>
<hr>
<%
    //获取request对象
    HttpServletRequest req = (HttpServletRequest) pageContext
            .getRequest();
    // pageContext包含Request和Response
    // HttpServletResponse resp = (HttpServletResponse) pageContext.getResponse();
    //设置page范围内属性
    pageContext.setAttribute("书名", "《Java程序设计》",pageContext.PAGE_SCOPE);
    //设置request范围内属性
    req.setAttribute("书名", "《Java Web程序设计》");
    pageContext.setAttribute("书名2", "《Java Web程序设计》(第2版)",pageContext.REQUEST_SCOPE);
    //设置session范围内属性
    pageContext.setAttribute("图书名", "《Java Sesion详解》", pageContext.SESSION_SCOPE);

    //获得的page范围属性
    String str1 = (String)pageContext.getAttribute("书名",
            pageContext.PAGE_SCOPE);
    //获得的request范围属性
    String str2 = (String)pageContext.getAttribute("书名",
            pageContext.REQUEST_SCOPE);
    String str3 = (String)pageContext.getAttribute("书名2",
            pageContext.REQUEST_SCOPE);
    //获得的request范围属性
    String str4 = (String)pageContext.getAttribute("图书名",
            pageContext.SESSION_SCOPE);
    //获得的默认范围属性
    String str5 = (String)pageContext.getAttribute("书名");
    String str6 = (String)pageContext.findAttribute("书名");
%>
<%="page范围 getAttribute(\"书名\"):"+str1 %><br>
<%="request范围 getAttribute(\"书名\"):"+str2 %><br>
<%="request范围 getAttribute(\"书名2\"):"+str3 %><br>
<%="session范围 getAttribute(\"图书名\"):"+str4 %><br>
<%="pageContext.getAttribute(\"书名\"):"+str5 %><br>
<%="pageContext.findAttribute(\"书名\"):"+str6 %><br>
</body>
</html>

运行结果:

图13 pageContext.set|get|findAttribute 设置、提取、查找属性

5.4 exception对象

在JSP页面中,经常需要处理一些异常信息,处理异常信息可以通过exception对象实现。exception对象是java.lang.Exception类的实例对象,它用于封装JSP中抛出的异常信息。

需要注意的是,exception对象只有在错误处理页面才可以使用,即page指令中指定了属性<%@ page isErrorPage="true"%>的页面。

异常处理程序 12error.jsp @page定义中 isErrorPage="true"

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>出错处理</title>
</head>
<body>
    <h2>异常信息</h2>
    <hr>
    <!-- 显示异常信息 -->
    <%=exception.getMessage()%><br />
</body>
</html>

指定异常处理程序 12exception_zxx.jsp @page定义中 errorPage="12error.jsp"

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" errorPage="12error.jsp"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>exception object test</title>
</head>
<body>
    <h1>异常隐藏对象测试</h1>
    <%
        int a = 3;
        int b = 0;
    %>
    输出结果为:<%=(a / b)%><!--此处会产生异常  -->
</body>
</html>

运行结果:

图14 exception对象测试

13table_zxx.jsp 应用Java程序片段动态生成表格

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>应用Java程序片段动态生成表格</title>
</head>
<body>
  <h1>应用Java程序片段动态生成表格</h1>
  <hr>
  <%
    String[] bookName = {"JavaWeb程序开发入门","JavaWeb程序开发进阶","Java基础案例教程"};
  %>
  <table border="1" align="center" style="font-size:25px;">
    <tr>
      <td align="center">编号</td>
      <td align="center">书名</td>
    </tr>
    <%
      for (int i=0;i<bookName.length;i++){
    %>
    <tr>
      <td align="center"><%=i %></td>
      <td align="center"><%=bookName[i]%></td>
    </tr>
    <%}%>
  </table>
</body>
</html>
图15 应用Java程序片段动态生成表格

任务:将页面转发到用户登录页面

在实际的项目开发过程中,Servlet 中的service() 方法由Servlet 容器调用,所以一个 Servlet 的对象是无法调用另一个 Servlet 的方法的,但是在实际项目中,对于客户端请求做出的响应可能会比较复杂,例如用户登录,需要多个Servlet 来协作完成,这就需要使用请求转发技术了。本任务要求使用请求转发动作元素将页面转发到用户登录页面。

web/页面转发/login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
<form name="form1" method="post" action="">
    用户名:  <input name="name" type="text" id="name" style="width:
      200px"><br><br>&nbsp;&nbsp;&nbsp;码:  <input name="pwd" type="password" id="pwd" style="width: 200px"><br><br>
    <input type="submit" name="Submit" value="提交">
</form>
</body>
</html>

web/页面转发/forward_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>中转页</title>
</head>
<body>
    <jsp:forward page="login.jsp"/>
</body>
</html>

运行结果:

图16 页面转发

任务:网上蛋糕商城JSP页面

注册页面动态包含头部和脚部jsp:include page="header.jsp|footer.jsp"

web/用户注册/header.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div class="header">
    <div class="container">
        <nav class="navbar navbar-default" role="navigation">
            <!--navbar-header-->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li><a href="/index" >首页</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle " data-toggle="dropdown">商品分类
                            <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu multi-column columns-2">
                            <li>
                                <div class="row">
                                    <div class="col-sm-12">
                                        <h4>商品分类</h4>
                                    </div>
                                </div>
                            </li>
                        </ul>
                    </li>
                    <li><a href="#" >热销</a></li>
                    <li><a href="#" >新品</a></li>
                    <li><a href="#" class="active">注册</a></li>
                    <li><a href="#" >登录</a></li>
                </ul>
                <!--/.navbar-collapse-->
            </div>
            <!--//navbar-header-->
        </nav>
        <div class="header-info">
            <div class="header-right search-box">
                <a href="javascript:;">
                    <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                </a>
                <div class="search">
                    <form class="navbar-form" action="/">
                        <input type="text" class="form-control" name="keyword">
                        <button type="submit" class="btn btn-default" aria-label="Left Align">
                            搜索
                        </button>
                    </form>
                </div>
            </div>
            <div class="header-right cart">
                <a href="goods_cart.jsp">
                    <span class="glyphicon glyphicon-shopping-cart " aria-hidden="true">
                        <span class="card_num"></span>
                    </span>
                </a>
            </div>
            <div class="clearfix"> </div>
        </div>
        <div class="clearfix"> </div>
    </div>
</div>
<!--//header-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!--footer-->
<div class="footer">
    <div class="container">
        <div class="text-center">
            <p>挚诚天下(张晓轩) www.jxpzhaojiang.cn © 版权所有</p>
        </div>
    </div>
</div>
<!--//footer-->

web/用户注册/user_register_zxx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>用户注册</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/bootstrap.css">
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!--header-->
    <jsp:include page="header.jsp"/>
    <!--//header-->
    <!--account-->
    <div class="account">
        <div class="container">
            <div class="register">
                <form action="/user_rigister" method="post">
                    <div class="register-top-grid">
                        <h3>注册新用户</h3>
                        <div class="input">
                            <span>用户名 <label style="color:red;">*</label></span>
                            <input type="text" name="username" placeholder="请输入用户名" required="required">
                        </div>
                        <div class="input">
                            <span>邮箱 <label style="color:red;">*</label></span>
                            <input type="text" name="email" placeholder="请输入邮箱" required="required">
                        </div>
                        <div class="input">
                            <span>密码 <label style="color:red;">*</label></span>
                            <input type="password" name="password" placeholder="请输入密码" required="required">
                        </div>
                        <div class="input">
                            <span>收货人<label></label></span>
                            <input type="text" name="name" placeholder="请输入收货">
                        </div>
                        <div class="input">
                            <span>收货电话<label></label></span>
                            <input type="text" name="phone" placeholder="请输入收货电话">
                        </div>
                        <div class="input">
                            <span>收货地址<label></label></span>
                            <input type="text" name="address" placeholder="请输入收货地址">
                        </div>
                        <div class="clearfix"> </div>
                    </div>
                    <div class="register-but text-center">
                       <input type="submit" value="提交">
                       <div class="clearfix"> </div>
                    </div>
                </form>
                <div class="clearfix"> </div>
            </div>
        </div>
    </div>
    <!--//account-->
    <!--footer-->
    <jsp:include page="footer.jsp"/>
    <!--//footer-->
</body>
</html>

运行结果:

图17 注册新用户
图18 ch06源代码文件结构

返回