您的位置:首页 > 运维架构 > Tomcat

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

2018-03-26 19:29 495 查看

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来发布。

通过浏览器访问以下URL,Servlet容器仅仅对sum.jsp文件进行预编译:http://localhost:8080/hi?jsp_precompile=true
Servlet容器会根据该JSP文件生成相应的Servlet源文件和类文件,可以在tomcat的/work目录中找到。
把work目录中的类(.class)文件复制到app应用的WEB-INF/classes目录的相应子目录下。
在web.xml文件中配置该Servlet类。
删除应用中的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类的相关方法来进行请求转发和包含操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: