首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在JSP页面中打印错误堆栈跟踪?

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

Stack Overflow用户
提问于 2011-11-15 19:56:14
回答 6查看 52K关注 0票数 23

我在web.xml中设置了如下错误页面:

代码语言:javascript
复制
 <error-page>
  <exception-type>java.lang.Exception</exception-type>
  <location>/errors/error.jsp</location>
 </error-page>

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

EN

回答 6

Stack Overflow用户

发布于 2015-08-19 14:49:44

使用JSP scriptlet是十年来一直不赞成的做法。你最好是avoid它。

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

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

代码语言:javascript
复制
${pageContext.out.flush()}

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

代码语言:javascript
复制
${exception.printStackTrace(pageContext.response.writer)}

完整示例:

代码语言:javascript
复制
<%@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语句:

代码语言:javascript
复制
<%@page pageEncoding="UTF-8" isErrorPage="true" %>
...
<pre>${pageContext.out.flush();exception.printStackTrace(pageContext.response.writer)}</pre>

如果由于某种原因不能使用isErrorPage="true" (因此${exception}隐式对象不可用),那么只需替换为${requestScope['javax.servlet.error.exception']}即可

代码语言:javascript
复制
<%@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?

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

代码语言:javascript
复制
<%@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>
票数 14
EN

Stack Overflow用户

发布于 2011-11-15 20:00:18

在错误页面上,只需执行以下操作:

代码语言:javascript
复制
<jsp:scriptlet>
    exception.printStackTrace(response.getWriter())
</jsp:scriptlet>

尽管这回避了一个问题:用户将如何处理异常。为什么不将异常写到错误日志中,这样它就会持久存在,并且可以在用户投诉后返回到它?

票数 3
EN

Stack Overflow用户

发布于 2015-08-19 08:12:14

或者,为了避免在jsp中使用scriptlet,可以使用jstl:

代码语言:javascript
复制
<%@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文件中的脚本:

代码语言:javascript
复制
<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8135980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档