Struts2中的声明式异常的处理机制

    技术2024-11-12  25

    完整版见https://jadyer.github.io/

    这是一个Struts2.1.8.1应用,代码如下

    首先是web.xml

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>exceptionTest.jsp</welcome-file> </welcome-file-list> </web-app>

    然后是用于输入用户名和密码以测试异常的exceptionTest.jsp页面

    <%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <h2>Struts2中的声明式异常的处理机制</h2> <h4>初始姓名和密码为<font color="blue"><b>admin</b></font>和<font color="blue"><b>jadyer</b></font></h4> <s:form action="exceptiontest" theme="simple"> 姓名:<s:textfield name="username"/><br/> 密码:<s:password name="password"/><br/> <s:submit value="声明式异常测试"/> </s:form>

    用户名和密码均正确时显示的result.jsp页面

    <%@ page language="java" pageEncoding="UTF-8"%> <h2>Login Success</h2>

    当用户名无效时显示异常信息的usernameInvalid.jsp页面

    <%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <h2>用户名不正确时的异常提示</h2> 使用EL表达式输出:${exception.message}<br/><br/><br/> 使用<s:property>输出:<s:property value="exception.message"/><br/><br/><br/> <s:property value="exceptionStack"/> <%-- =================================================================== 可以采用两种方式在页面中输出异常提示信息 【第一种】${exception.message} 【第二种】<s:property value="exception.message"/> exception对应产生的Exception对象 exception.message指的是对象的属性 这里的message就是在UsernameException中定义的message属性 =================================================================== 如果将result设为为type="redirect"的话,即客户端跳转 那么在页面中将无法接收<s:property value="exception"/>信息 所以如果想在页面中打印出异常信息的话,就应该将type设置为服务器跳转 所谓的服务器跳转就是将type设置为dispatcher,或者是不设置,按照默认 =================================================================== 【补充】<s:property/>标签还可以打印出堆栈信息 即<s:property value="exceptionStack"/> 其中exceptionStack是固定不变的,不是随便写的 =================================================================== 在实际开发中,有的人会这么写 <!-- <s:property value="exception"/> <HR> <s:property value="exceptionStack"/> --> 也就是说在给用户显示异常信息的页面中打印输出人性化的提示信息 并且在该页使用<!-- -->注释掉原本需要打印的异常信息 这样的好处就是在页面中,用户看到的仍是我们设定给他的提示信息 但是我们在这个页面中右键查看源代码时 就可以在源代码中查看本应在控制台中输出的异常信息和异常堆栈信息了 也就是说将异常信息和堆栈信息隐藏在异常页面的源代码中,而不显示给用户 比较适用于项目上线之后,当出现错误时,方便查看错误信息,快速修正BUG =================================================================== --%>

    当密码无效时显示异常信息的passwordInvalid.jsp页面

    <%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <h2>密码不正确时的异常提示</h2> 使用EL表达式输出:${exception.message}<br/><br/><br/> 使用<s:property>输出:<s:property value="exception.message"/><br/><br/><br/> <s:property value="exceptionStack"/>

    关于Struts2的配置文件struts.xml

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="struts2.1" extends="struts-default"> <global-results> <result name="passwordInvalid">/passwordInvalid.jsp</result> </global-results> <global-exception-mappings> <!-- <exception-mapping result="SQLInvalid" exception="java.lang.SQLException"/> --> <exception-mapping result="passwordInvalid" exception="com.jadyer.exception.PasswordException"/> </global-exception-mappings> <action name="exceptiontest" class="com.jadyer.action.ExceptionTestAction"> <exception-mapping result="usernameInvalid" exception="com.jadyer.exception.UsernameException"/> <result name="usernameInvalid">/usernameInvalid.jsp</result> <result name="success">/result.jsp</result> </action> </package> </struts> <!-- *******************【Struts2的声明式异常的处理】*************************************************************** --> <!-- Struts2本身可以看做是一个空的容器,里面放置了很多的拦截器使它充实,我们所发送的请求都需要通过一个个的拦截器 --> <!-- 而它的声明式的异常处理就是由defaultStack默认拦截器中的exception拦截器来实现的 --> <!-- 异常发生时,exception拦截器就捕获异常,然后从配置文件中读取异常配置的相关信息,并进行相关处理 --> <!-- *******************【Struts2的异常的配置】******************************************************************** --> <!-- 关于异常的配置,跟Struts1.X一样有两种类型的异常,即全局性异常和局部性异常 --> <!-- 而且<exception-mapping/>元素有两个必填的属性,分别是result和exception --> <!-- exception属性表示的是程序中所抛出的异常的类型,它的值是包名加类名的全称 --> <!-- 一旦程序遇到exception属性对应的异常时,它就会转到result属性所标识的视图资源中,然后呈现给用户显示异常的界面 --> <!-- 比如说当Action抛出PasswordException异常时,它首先会到局部异常配置中查找PasswordException异常配置 --> <!-- 结果没有找到,然后它就转而到全局的异常配置中寻找。当它在全局异常配置中找到PasswordException的时候 --> <!-- 它也就得到了一个名为passwordInvalid的result。但接下来它不是直接到<global-results/>中匹配result --> <!-- 而是重新回到<action/>标签中寻找result为passwordInvalid的元素,结果是发现没有 --> <!-- 此时,它才会到<global-results/>中查找名字为passwordInvalid的result,然后就进入到对应的视图资源中 --> <!-- *********************************************************************************************************** -->

    自定义的UsernameException异常类

    package com.jadyer.exception; /** * 自定义的UsernameException异常类 * @see Java中的自定义异常都要直接或间接的继承java.lang.Exception * @see 一般的自定义异常的模型都是像这个类这样定义的 */ @SuppressWarnings("serial") public class UsernameException extends Exception { private String message; public UsernameException(String message){ this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }

    自定义的PassowordException异常类

    package com.jadyer.exception; /** * 自定义的PasswordException异常类 */ @SuppressWarnings("serial") public class PasswordException extends Exception { private String message; public PasswordException(String message){ super(message); this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }

    最后是用来处理异常分发的ExceptionTestAction.java

    package com.jadyer.action; import com.jadyer.exception.PasswordException; import com.jadyer.exception.UsernameException; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class ExceptionTestAction extends ActionSupport { private String username; private String password; /* 两个属性的setter和getter略 */ /** * 在execute()的方法体中之所以可以throw任何类型的异常 * 关键原因就在于execute()方法本身在声明的时候就throws Exception * 所以说Exception的任何一个子类异常都可以在execute()方法体中throw * 这就为自定义异常提供了很大的方便 */ public String execute() throws Exception { if(!"admin".equals(this.getUsername())){ throw new UsernameException("用户名无效"); //username invalid }else if(!"jadyer".equals(this.getPassword())){ throw new PasswordException("密码无效"); //password invalid }else{ return SUCCESS; //username and password is allRight } } }

    最新回复(0)