Tomcat与JavaWeb 3.3 JSP的异常处理、发布和PageContext

本文介绍了JSP异常处理机制及实现方法,包括如何设置异常处理页面和利用PageContext类的功能。同时,还讲解了JSP的发布流程,涉及URL映射修改、预编译JSP文件以及PageContext类的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.    JSP异常处理

如同普通的Java程序一样,JSP在运行时也有可能抛出异常。在发生异常的场合,可以通过下面的指令将请求转发给另一个专门处理异常的网页:

<%@ page errorPage="errorPage.jsp"%>
以上errorPage.jsp是一个专门负责处理异常的网页,在这个处理异常的网页中,应该通过如下语句将该网页声明为异常处理网页:
<%@ page isErrorPage="true"%>

处理异常的网页可以直接访问exception隐含对象,获取当前异常的详细信息,例如:

<p>
    错误原因为:<% exception.printStackTrace(new PrintWriter(out));%>
</p>

抛出异常的JSP文件与处理异常的JSP文件之间为请求转发关系,因此它们共享请求范围内的共享数据。

下面创建一个可能会抛出异常的JSP网页sum.jsp,在这个网页中读取客户请求中的两个参数num1和num2,把它们转化为整数类型,再对其求和,最后把结果输出到网页上。sum.jsp中的toInt()方法负责将字符串转化为整数。

如果客提供的请求参数不能转化为整数,Integer.parseInt(num)方法就会抛出NumberFormatException,这是Servlet容器自动把客户请求转发到errorPage.jsp。下面分别为源代码:
sum.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page errorPage="errorPage.jsp" %>
<html>
<head>
    <title>求和</title>
</head>
<body>
    <%! private int toInt(String num){
        return Integer.valueOf(num);
    }
    %>
    <%
        int num1=toInt(request.getParameter("num1"));
        int num2=toInt(request.getParameter("num2"));
    %>
    <p>
        运算结果为:<%=num1%>+<%=num2%>=<%=num1+num2%>
    </p>
</body>
</html>
errorPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page isErrorPage="true" %>
<%@page import="java.io.PrintWriter" %>
<html>
<head>
    <title>Error Page</title>
</head>
<body>
    <p>
        你输入的参数(num1=<%=request.getParameter("num1")%>,num2=<%=request.getParameter("num2")%>)有错误。
    </p>
    <p>
        错误原因为:<% exception.printStackTrace(new PrintWriter(out));
    %>
    </p>
</body>
</html>
访问如下地址:localhost:8080/sum.jsp?num1=100&num2=200 ,此时sum.jsp正常运行:

再将URL中的参数num2的值改为two: localhost:8080/num1=100&num2=two  ,由于num2参数不能转化为整数,sum.jsp在运行时会抛出NumberFormatException,这时客户请求转到errorPage.jsp,生成的网页如图所示:

注意到这时URL并没有变,这符合 请求转发的规则。

2.    JSP的发布

    1)    JSP映射
可以通过在web.xml中增加配置的方法来修改JSP的URL映射,例如:
web.xml
    <servlet>
        <servlet-name>sumjsp</servlet-name>
        <jsp-file>sum.jsp</jsp-file>
    </servlet>
    <servlet-mapping>
        <servlet-name>sumjsp</servlet-name>
        <url-pattern>/hi</url-pattern>
    </servlet-mapping>
加入以上代码后,就可以通过<url-pattern>指定的URL来访问对应JSP文件了。

    2)    预编译JSP
当JSP文件被客户端第一次请求访问时,Servlet容器需要先把JSP文件编译为Servlet类之后才能运行,这一过程会延长客户端等待响应结果的时间,可能会给客户留下不好的印象。为避免这一问题,可以对JSP文件进行预编译。
JSP规范为JSP规定了一个特殊的请求参数jsp_precompile,它的取值可以为true或false。如果请求参数jsp_precompile的值为true,那么Servlet容器仅仅对客户端请求的JSP文件进行预编译,即把JSP文件转换为Servlet类,但不会运行Servlet。

    下面按照如下步骤对sum.jsp进行预编译,并把它作为Servlet来发布。

  1. 通过浏览器访问以下URL,Servlet容器仅仅对sum.jsp文件进行预编译:http://localhost:8080/hi?jsp_precompile=true
    Servlet容器会根据该JSP文件生成相应的Servlet源文件和类文件,可以在tomcat的/work目录中找到。
  2. 把work目录中的类(.class)文件复制到app应用的WEB-INF/classes目录的相应子目录下。
  3. 在web.xml文件中配置该Servlet类。
  4. 删除应用中的JSP文件,因为已经有Servlet类文件了。

按照上述方式预编译和发布JSP文件有两个作用:

  • 提高了服务器对客户端请求访问JSP文件的响应速度。因为无论客户端是否首次访问某个JSP文件,服务器都只需运行与JSP文件对应的Servlet。
  • 如果在Web应用被发布后,不希望其他人查看或者更新JSP源代码,那么对JSP文件进行预编码刚好能满足这一要求。因为在发布后的Web应用中根本没有JSP文件,只有与JSP文件对应的Servlet的.class文件。

3.    PageContext抽象类

JSP API提供了一个非常实用的类:javax.servlet.jsp.PageContext抽象类,它继承了javax.servlet.jsp.JspContext。PageContext类是JSP文件的得力助手,在JSP文件中使用PageContext的场合主要包括:

  • JSP文件中的Java程序片段。
  • JSP文件中的自定义标签的处理类(参见后续章节)。

PageContext类中的方法可以分为以下几种:

  • 用于向各种范围内存取属性的方法。
  • 用于获得由Servlet容器提供的其他对象的引用的方法。
  • 用于请求转发和包含的方法。
    1)    向各种范围内存取属性的方法

在PageContext类中提供了一组向各种范围内存取属性的方法,如下所示。

  • getAttribute(String name):返回页面范围内的特定属性的值。
  • getAttribute(String name, int scope):返回参数scope指定的范围内的特定属性的值。
  • setAttribute(String name, Object value,int scope):向参数scope指定的范围内存放属性。
  • removeAttributes(String name,int scope):从参数scope指定的范围内删除特定属性。
  • findAttribute(String name):依次从页面范围、请求范围、会话范围和Web应用范围内寻找参数name指定的属性。
  • int getAttributesScope(java.lang.String name):返回参数指定的属性所属的范围,如果所有的范围内都不存在该属性,就返回0.

以上方法中是scope参数指定属性的范围,可选值为PageContext类的4个静态常量:

  • PageContext.PAGE_SCOPE = 1 :表示页面范围。
  • PageContext.REQUEST_SCOPE = 2 :表示请求范围,我们已经学习过请求范围的概念。
  • PageContext.SESSION_SCOPE = 3 :表示会话范围。
  • PageContext.APPLICATION_SCOPE = 4: 表示Web应用范围,其概念参见第一章第三节。Web应用范围

PageContext对象由Servlet容器负责创建,JSP文件可以直接通过固定变量pageContext来引用隐含的PageContext对象。

以下代码向请求范围内存放了一个username属性:

<% pageContext.setAttribute("username","Tomcat",PageContext.REQUEST_SCOPE);%>
它与以下代码是等价的:
<% request/setAttribute("username","Tomcat");%>

以下代码试图读取Web应用范围内的count属性:

<% Counter counter = (Counter)pageContext.getAttribute("count",PageContext.APPLICATION_SCOPE);%>
它与以下代码等价(application引用ServletContext隐含对象):
<%Counter counter = application.getAttribute("count");%>
    2)    用于获得由Servlet容器提供的其他对象的引用的方法

PageContext类的以下方法用于获得由Servlet容器提供的ServletContext、HttpSession、ServletRequest和ServletResponse等对象。

  • getPage():返回域当前JSP对应的Servlet实例。
  • getRequest():返回ServletRequest对象。
  • getResponse():返回ServletResponse对象。
  • getServletConfig():返回ServletConfig对象。
  • getServletContext():...
  • getSession():返回HttpSession对象。
  • getOut():返回一个用于输出响应正文的JspWriter对象。

在JSP文件中的Java程序片段中,可直接通过application、request和response等固定变量来引用对应的对象。而在自定义的JSP标签的处理类中,无法使用这些固定变量,此时就需要依靠PageContext类的相关方法来得到ServletContext等对象。

    3)    用于请求转发和包含的方法

  • forward(String relativeUrlPath):用于把请求转发给其他Web组件。
  • include(String relativeUrlPath):用于包含其他Web组件。

在JSP文件中可以用专门的JSP标记(如<jsp:forward><jsp:include>标记)来进行请求转发和包含操作,而在自定义的JSP标签的处理类中,无法使用JSP标记,此时就需要依靠PageContext类的相关方法来进行请求转发和包含操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值