3.8.2 声明式异常捕捉
Struts 2的异常处理机制是通过在struts.xml文件中配置<exception-mapping .../>元素完成的,配置该元素时,需要指定两个属性。
exception:此属性指定该异常映射所设置的异常类型。
result:此属性指定Action出现该异常时,系统转入result属性所指向的结果。
根据<exception-mapping .../>元素出现位置的不同,异常映射又可分为两种。
局部异常映射:将<exception-mapping .../>元素作为<action .../>元素的子元素配置。
全局异常映射:将<exception-mapping .../>元素作为<global-exception-mappings>元素的子元素配置。
与前面的<result .../>元素配置结果类似,全局异常映射对所有的Action都有效,但局部异常映射仅对该异常映射所在的 Action 内有效。如果局部异常映射和全局异常映射配置了同一个异常类型,在该Action内,局部异常映射会覆盖全局异常映射。
下面的应用同样是一个简单的登录应用,在登录页面输入用户名和密码两个参数后,用户提交请求,请求将被如下的Action类处理。
程序清单:codes\03\3.8\ExceptionHandler\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java
// 处理用户请求的Action类 public class LoginAction implements Action { // 使用两个属性来封装用户请求参数 private String username; private String password; // 使用tip属性来封装服务器处理后的结果 private String tip; // username属性的setter和getter方法 public void setUsername(String username) { this.username = username; } public String getUsername() { return (this.username); } // password属性的setter和getter方法 public void setPassword(String password) { this.password = password; } public String getPassword() { return (this.password); } // tip属性的setter和getter方法 public void setTip(String tip) { this.tip = tip; } public String getTip() { return tip; } // 处理用户请求的execute方法,该方法抛出所有异常类型 public String execute() throws Exception { // 手动抛出异常 if (getUsername().equalsIgnoreCase("user")) { throw new MyException("自定义异常"); } // 手动抛出异常 if (getUsername().equalsIgnoreCase("sql")) { throw new java.sql.SQLException("用户名不能为SQL"); } if (getUsername().equals("crazyit") && getPassword().equals("leegang") ) { setTip("哈哈,服务器提示!"); return SUCCESS; } else { return ERROR; } } }
因为本应用没有通过 Action 来调用业务逻辑组件,因此系统不会直接抛出异常。为了验证Struts 2的异常处理框架,我们采用手动方式抛出两个异常:MyException和SQLException,其中MyException异常是一个自定义异常。
下面通过struts.xml文件来配置Struts 2的异常处理机制,本系统的struts.xml文件如下。
程序清单:codes\03\3.8\ExceptionHandler\WEB-INF\src\struts.xml
<?xml version="1.0" encoding="GBK" ?> <!-- 指定Struts 2配置文件的DTD信息 --> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <!-- 配置Struts 2配置文件的根元素 --> <struts> <package name="crazyit" extends="struts-default"> <!-- 此处定义所有的全局结果 --> <global-results> <!-- 名为sql的结果,映射到/WEB-INF/content/exception.jsp页面 --> <result name="sql">/WEB-INF/content/exception.jsp</result> <!-- 名为root的结果,映射到/WEB-INF/content/exception.jsp页面 --> <result name="root">/WEB-INF/content/exception.jsp</result> </global-results> <!-- 此处定义所有的全局异常映射 --> <global-exception-mappings> <!-- 当Action抛出SQLException异常时,转入名为sql的结果 --> <exception-mapping exception="java.sql.SQLException" result= "sql"/> <!-- 当Action抛出Exception异常时,转入名为root的结果 --> <exception-mapping exception="java.lang.Exception" result="root"/> </global-exception-mappings> <!-- 下面配置本系统的Action --> <action name="login" class="org.crazyit.struts2.action.LoginAction"> <!-- 当Action抛出MyException异常时,转入名为my的结果 --> <exception-mapping exception="org.crazyit.struts2.exception.MyException" result="my"/> <!-- 下面定义了三个结果 --> <result name="my">/WEB-INF/content/exception.jsp</result> <result name="error">/WEB-INF/content/error.jsp</result> <result name="success">/WEB-INF/content/welcome.jsp</result> </action> <action name="*"> <result>/WEB-INF/content/{1}.jsp</result> </action> </package> </struts>
上面的配置文件定义了三个异常映射,指定系统出现如下三个异常时的处理策略。
org.crazyit.struts2.exception.MyException:该异常映射使用局部异常映射完成,当Action的execute方法抛出该异常时,系统转到名为my的结果。
java.sql.SQLException:该异常映射使用全局异常映射完成,当Action的execute方法抛出该异常时,系统转到名为sql的结果。
java.lang.Exception:该异常映射使用全局异常映射完成,当 Action 的 execute 方法抛出该异常时,系统转到名为root的结果。
当然,系统中也通过局部结果定义、全局结果定义的方式定义了 my、sql 和 root 三个结果。当定义异常映射时,通常需要注意:全局异常映射的result属性值通常不要使用局部结果,局部异常映射的result属性值既可以使用全局结果,也可以使用局部结果。
注意
全局异常映射的result属性值通常不要使用局部结果,局部异常映射的result属性值既可以使用全局结果,也可以使用局部结果。