阿帕奇支柱,Web应用程序框架,可以帮助开发人员获得的Java网络应用程序并在旁边的任何时间运行,使用模型-视图-控制器框架。创建一个伟大的应用程序的一个重要部分是正确处理错误和异常。Struts可以在应用程序中处理某些类型的用户条目验证UI标记ActionError等。但是当你的应用程序抛出一个异常时呢?你不希望你的用户面对什么都不是,除了不可穿透Tomcat堆栈跟踪页面。令人高兴的是,Struts的可以很容易地设置自定义异常处理,这样可以使生活更容易为你的用户,如果确实存在错误。
我假设您在Tomcat上运行Struts。如果使用另一个服务器,可能需要稍微不同地部署web应用程序,但是Struts代码本身应该是相同的。
默认的异常处理程序
在我们开始编写我们自己的错误处理代码,让我们快速浏览一下错误页面你,如果你不把任何特殊处理(如果你是一个非Tomcat服务器上运行的可能是不同的)做的。我们将编辑MyStruts.java(从这之前的教程)抛出异常:
public String execute()抛出异常{抛出new NullPointerException();}}
重新编译(CD WEB-INF /;的javac -cp LIB / XWork的核 - 2.3.4.1.jar -d类的src /示例/ MyStruts.java
),重新启动Tomcat,并访问http://本地主机:8080 / mystruts / MyStruts。你会看到一个相当难看的HTTP 500页上有一个大的堆栈跟踪:这可能对您有用作为一个开发人员,但它令人不安对于一般的最终用户。
创建一个自定义错误页面
处理这个问题最简单的方法就是创建一个自定义错误页面,并将错误结果直接指向该页面。在根mystruts目录中创建error.jsp:
<%@标签库前缀= “S” URI = “http://www.openlogic.com/struts-tags” %> 的Struts 2错误页 H1> BODY> HTML>
如果MyStruts中有异常,可以将其设置为加载。打开WEB-INF/classes/struts.xml,在MyStruts action部分添加几行代码:
<异常映射异常= " . lang。异常" result="error" /> /response。jsp /input。结果jsp < / > <结果name = "错误" > /错误。jsp
该异常映射
line将任何异常(因为所有Java异常都是Java .lang.Exception的后代)映射到“错误”结果。这个结果在几行之后定义,并指向/error.jsp。重启Tomcat并再次访问http://localhost:8080/mystruts/mystruts。这一次你应该看到你的自定义错误页面:
在浏览器中显示异常信息
当前错误页比HTTP 500默认的漂亮,但它的信息量要少得多。这是在某些方面(用户不要在由堆栈跟踪信息所淹没一般想要的,它可以是一个安全风险,显示大量的堆栈跟踪输出的)好,但它使棘手跟踪问题。令人高兴的是,如果你想显示的信息,Struts还提供了一种方式更人性化的方式显示它。
编辑再次的error.jsp,并添加几个属性:
<%@标签库前缀= “S” URI = “http://www.openlogic.com/struts-tags” %> MyStruts错误页 H1> 抱歉,MyStruts有问题! H4>
请邮件,提供以下信息管理员,我们会尽快就可以了。 p>
例外名称得到的东西再工作: b>
p>
异常详细信息: b> p> BODY> HTML>
正如你所料,例外
属性返回最后一个异常,而exceptionStack
属性返回最后一个异常的堆栈跟踪。重启Tomcat,重新加载页面,你会看到你的堆栈跟踪回来了:
同样,一定要注意显示这些信息可能会带来安全风险。仔细考虑想要向终端用户显示多少信息;最佳用量可能会因最终用户的不同而有所不同。
其他改进
如上代码所示,您必须为每个操作指定一个异常处理程序,这可能会导致大量工作。为了简化起见,可以声明一个全局异常处理程序。编辑struts.xml,看起来像这样:
<全局异常-映射> <异常-映射异常="java.lang。异常" result="error" /> 全局-异常-mappings> <结果名称= "成功" > /响应。jsp /input。结果jsp < / > <结果name = "错误" > /错误。jsp
这里,这个包中的所有异常都将由全局异常映射处理,该映射再次将它们发送到“error”结果。然而,“错误”的结果仍然是宣布在每个动作的基础上,这意味着你可以在全球基础上划分不同的错误(因此所有安全异常处理不同于所有其他的异常,例如),但个性化每个错误响应包内的具体行动。
但是,您可能希望使用相同的错误结果所有包内的错误。在这种情况下,您需要在struts中声明一个全局结果。xml,以及全局异常映射:
<支柱> <包名称= “默认” 的延伸= “支柱默认”> <全局结果> <结果名称= “错误”> / error.jsp文件导致> 全局结果> <全局exception-映射> <异常映射异常= “java.lang.Exception的” 结果= “错误”/> 全局异常映射> <动作名称= “mystruts” 类= “example.mystruts”> <结果名称=”成功 “> /的response.jsp 结果> <结果名称=” 输入”类型= “重定向”> /的Input.jsp 导致> 动作> 包> 支柱>
现在,“错误”被宣布为一个全球性的结果,并从任何异常任何这个包内的动作发送到error.jsp页面页面。
注意!在这个XML文件中,元素的顺序很重要。如果你有global-exception-mapping
部分之前该全球结果
节,你会得到,这将产生在Tomcat日志中这样的行错误:
org.xml.sax.SAXParseException:通过引起????结果类型,拦截器,默认拦截-ref时,默认动作-ref时,缺省类-REF的元素类型 “包” 必须匹配“(内容?,全局的结果吗?,全球异常映射?,行动*)”。
这样就指定了解析器期望看到的各种元素的顺序。
您还应该仔细考虑如何在代码中处理异常。例如,捕获异常可能比抛出异常更合适,在这种情况下(取决于您如何处理异常),您可能永远无法获得异常处理程序。您还可以选择以不同的方式处理不同类型的异常,甚至可以选择创建自己的异常类型(然后可以为其创建一个特定的Struts结果标记)来改善用户体验。所有这些都是设计和构建一个健壮、高质量应用程序的一部分。
启用记录
最后,Struts2ExceptionMappingInterceptor还提供了记录选项,您可以通过编辑struts.xml的设置:
< strtors > ERROR .....
请记住,这需要在文件中的正确位置;见上文对于其中的Struts期望看到包装元素的顺序。
这里我们创建了一个新的拦截器堆栈,称为myStrutsDefaultStack
的基础上,defaultStack
拦截器(由所识别的拦截-REF
元件)。这些是每当一个Action类方法被称为自动运行的拦截器。其中一个是ExceptionMappingInterceptor,它被命名为例外
的定义defaultStack
。最后,我们设置logEnabled
和LOGLEVEL
在这个拦截器的参数。
这意味着,当未捕获的异常被抛出,Struts的不仅处理它(你的错误导致的射击之一,因为我们已经设置了),同时也将其记录到Web服务器的控制台。(对于Tomcat,这应该是在你的默认日志目录,通常是$ CATALINA_HOME /日志。)您可以将级别设置为标准的日志级别(WARN,INFO,DEBUG,ERROR等)。有关调试Struts的更多信息,请参阅撑杆2个调试文档。
正确地处理错误是构建一个健壮且用户友好的应用程序的重要组成部分。Struts再次开始帮助您以最小的麻烦很好地管理错误——并在调试过程中提供了一些帮助。