如何在JSP页面中打印错误堆栈跟踪?

时间:2011-11-15 11:56:14

标签: java jsp exception servlets jstl

我在web.xml中设置了这样的错误页面:

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

现在我想在JSP上打印堆栈错误(当然只在开发模式下)。如何在JSP页面上打印堆栈错误?我没有为这个应用程序使用任何框架,因此我的程序只能使用默认的servlet API。

9 个答案:

答案 0 :(得分:21)

当请求转发到错误页面时,容器将设置以下参数。

  • javax.servlet.error.status_code
  • 中的javax.servlet.error.exception
  • javax.servlet.error.message
  • javax.servlet.error.request_uri
  • javax.servlet.error.servlet_name
  • javax.servlet.error.exception_type

在您的错误JSP中执行此操作,

<%request.getAttribute("javax.servlet.error.exception").printStackTrace(new java.io.PrintWriter(out))%>;

或者其他如果您的错误页面被定义为带有Page Directive的错误页面,

<%@ page isErrorPage="true" import="java.io.*"%>

异常 脚本变量将在JSP中声明。您可以使用

使用scriptlet打印脚本变量
exception.printStackTrace(new java.io.PrintWriter(out));

或者,

<jsp:scriptlet>
    exception.printStackTrace(response.getWriter())
</jsp:scriptlet>

答案 1 :(得分:20)

从内部设置的请求中获取参数,并使用它来打印和处理其他信息,例如causemessage

<c:set var="exception" value="${requestScope['javax.servlet.error.exception']}"/>

并打印stacktrace

<!-- Stack trace -->
<jsp:scriptlet>
  exception.printStackTrace(new java.io.PrintWriter(out));
</jsp:scriptlet>

另见

答案 2 :(得分:10)

使用JSP scriptlet是十年来不受欢迎的做法。你最好avoid

如果您已经使用EL 2.2或更新版本(Tomcat 7 +,JBoss AS 6 +,WildFly,GlassFish 3+等),并且对${instance.method()}形式的方法表达式有新的支持,那么您可以只需使用100%EL即可。

首先,您需要通过JspWriter#flush()显式刷新JSP编写器,以便所有前面的JSP模板输出真正写入servlet响应的编写器:

${pageContext.out.flush()}

然后,您可以将ServletResponse#getWriter()传递给Throwable#printStackTrace()

${exception.printStackTrace(pageContext.response.writer)}

完整示例:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
...
<pre>${pageContext.out.flush()}${exception.printStackTrace(pageContext.response.writer)}</pre>

如果您已经使用EL 3.0(Tomcat 8 +,WildFly,GlassFish 4+等),您甚至可以使用分隔EL语句的新分号运算符使其成为单个表达式:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
...
<pre>${pageContext.out.flush();exception.printStackTrace(pageContext.response.writer)}</pre>

如果由于某种原因无法使用isErrorPage="true"(因此${exception}隐式对象不可用),则只需用${requestScope['javax.servlet.error.exception']}代替:

<%@page pageEncoding="UTF-8" %>
...
<pre>${pageContext.out.flush()}${requestScope['javax.servlet.error.exception'].printStackTrace(pageContext.response.writer)}</pre>

如果您还没有使用EL 2.2,那么最好的办法就是创建自定义EL功能。细节可以在What is the good approach to forward the exception from servlets to a jsp page?

中找到

下面是一个更完整的错误页面示例,其中包含更多详细信息:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<ul>
    <li>Exception: <c:out value="${requestScope['javax.servlet.error.exception']}" /></li>
    <li>Exception type: <c:out value="${requestScope['javax.servlet.error.exception_type']}" /></li>
    <li>Exception message: <c:out value="${requestScope['javax.servlet.error.message']}" /></li>
    <li>Request URI: <c:out value="${requestScope['javax.servlet.error.request_uri']}" /></li>
    <li>Servlet name: <c:out value="${requestScope['javax.servlet.error.servlet_name']}" /></li>
    <li>Status code: <c:out value="${requestScope['javax.servlet.error.status_code']}" /></li>
    <li>Stack trace: <pre>${pageContext.out.flush()}${exception.printStackTrace(pageContext.response.writer)}</pre></li>
</ul>

答案 3 :(得分:5)

可能对你有帮助..
它将在浏览器中显示异常StackTrace

exception.printStackTrace(response.getWriter());  

<%
  try{
     int test = Integer.parseInt("hola");
  }catch(Exception e){
     **// HERE THE MAGIC BEGINS!!**
     out.println("<div id=\"error\">");
     e.printStackTrace(new java.io.PrintWriter(out));
    out.println("</div>");
    **// THE MAGIC ENDS!!**
  }
%>

如果你在error.jsp之上声明<% page isErrorPage="true" %>,那么你可以${exception}

访问抛出的异常(以及它的所有getter)
<p>Message: ${exception.message}  

了解更多.. Mapping Errors to Error Screens

答案 4 :(得分:3)

在错误页面上,只需执行:

<jsp:scriptlet>
    exception.printStackTrace(response.getWriter())
</jsp:scriptlet>

虽然这引出了一个问题:用户将如何处理异常。为什么不将错误写入错误日志,以便它保持不变,你可以在用户抱怨之后回复它?

答案 5 :(得分:3)

或者,为避免在jsp中使用scriptlet,请使用jstl:

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

<c:set var="exception" value="${requestScope['javax.servlet.error.exception']}"/>

<c:if test="${exception != null}">
  <h4>${exception}</h4>
  <c:forEach var="stackTraceElem" items="${exception.stackTrace}">
    <c:out value="${stackTraceElem}"/><br/>
  </c:forEach>
</c:if>

理想情况下,不应将scriptlet作为最佳做法。通过web.xml配置明确防止jsp文件中的scriplet:

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>

答案 6 :(得分:2)

Thrown Exception对象可用作名为'javax.servlet.error.exception'的请求属性。因此,在JSP中,您可以编写:

<% request.getAttribute("javax.servlet.error.exception").printStackTrace(new java.io.PrintWriter(out); %>

答案 7 :(得分:0)

您可以使用jstl核心库

1)在JSP文件顶部导入tablib

<%@ taglib prefi x=”c” uri=”http://java.sun.com/jsp/jstl/core” %>

2)使用标签

<c:catch var="myExceptionObject">
    Code that might throw Exception
<c:catch/>

<c:if test="${myExceptionObject} != null">
    There was an exception: ${myExceptionObject.message}
<c:if/>

答案 8 :(得分:0)

在error.jsp中添加以下行

<%Logger log = Logger.getLogger("error_jsp.class");
Exception e = (Exception)request.getAttribute("javax.servlet.error.exception");
log.debug(request.getAttribute("javax.servlet.error.message"));
e.printStackTrace();
log.debug(e.getStackTrace());%>