Struts中的异常处理

代码说话,是最有效的证明,请看。。

首先是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"> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>3</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>3</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>

然后是用于激活各种异常的用户登录页面login.jsp

<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %> <h2>演示Struts的异常处理</h2> <html:errors/> <h4> <font color="red">提示:</font>程序设定的用户名和密码分别为 <font color="blue"><strong>admin</strong></font>和 <font color="blue"><strong>jadyer</strong></font> </h4> <form action="login.do" method="POST"> 用户:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> <input type="submit" value="登录"> </form> <%-- ============================================================================================== 1、编程式异常 * 截获异常 * 创建相应的异常消息 * 传递异常消息 * 转向相应的页面处理异常 ============================================================================================== 2、声明式异常(自动处理的异常) * 在struts-config.xml文件中配置<exeception/>标签 * 理解局部和全局exception * 注意局部<exception/>标签需要配置到<forward/>标签的前面,详见DTD中的约束 ============================================================================================== 3、<exeception/>标签中的属性说明: * key:指异常信息对应的国际化消息文本,这个key值需要在国际化资源文件中定义 * type: 处理哪种异常 * path: 定义一但出现异常,需要转向页面 若不定义path,默认将使用<action>标签中input属性对应的页面 * scope:可以取值request和session,默认为request * handler:异常的处理类,struts默认采用org.apache.struts.action.ExceptionHandler 如果做个性化的异常处理可以继承此类覆写相应的方法 ============================================================================================== 4、参见:ErrorCodeExceptionHandler.java和AppExceptionHandler.java ============================================================================================== --%>

用户名和密码均正确时的登录成功页面login_success.jsp

<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %> <%-- 请将struts-html.tld文件放置在WEB-INF目录下 --%> <html:errors/>

然后是Struts1.x的核心配置文件struts-config.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="loginForm" type="com.jadyer.struts.form.LoginActionForm"/> </form-beans> <global-exceptions> <exception key="error.exception" type="com.jadyer.custom.AppException"/> </global-exceptions> <action-mappings> <action path="/login" type="com.jadyer.struts.action.LoginAction" name="loginForm" scope="request" validate="false" input="/login.jsp"> <forward name="success" path="/login_success.jsp"/> </action> </action-mappings> <message-resources parameter="res.MessageResources" /> </struts-config> <!-- *********************【演示Struts的声明式异常时,所用到的异常类】******************************************************************* --> <!-- <exception key="user.not.found" type="com.jadyer.struts.UserNotFoundException" path="/login_error.jsp"/> --> <!-- <exception key="user.password.error" type="com.jadyer.struts.PasswordErrorException" path="/login_error.jsp"/> --> <!-- <exception/>中key属性指异常信息对应的国际化消息文本,这个key值需要在国际化资源文件中定义,type属性指定处理的具体的哪种异常 --> <!-- path属性定义一旦出现异常,需要转向哪个页面。如果不定义path,默认情况下将转向到<action/>标签中input属性对应的页面 --> <!-- 也就是说,当发生UserNotFoundException异常的时候,就显示国际化资源文件中的user.not.found所对应的国际化提示信息 --> <!-- 由于此时所出现的异常,也被Struts设到ERROR_KEY上了,所以在页面中便可通过<html:errors/>或者<html:messages/>获取异常 --> <!-- 但是,如果同时设定的input和path属性,那么path的优先级要高一些,异常信息会优先转向到path属性所指向的页面 --> <!-- <exception/>和<forward/>类似,它也有一个全局的概念 --> <!-- 所以,这种异常通常被定义成全局的。这样一来,只要Action发生这种异常,那么它就会自动按照全局异常中的设置进行相应的转向或处理 --> <!-- 如果全局异常中没有指定path值,那么当发生全局异常时,会自动转向到各自的<action/>标签中所设定的input对应的页面 --> <!-- *********************【演示Struts的个性化异常时,所用到的异常类==》此时用到了国际化资源文件】******************************************* --> <!-- <exception key="error.code" type="com.jadyer.custom.ErrorCodeException" handler="com.jadyer.custom.ErrorCodeExceptionHandler"/> --> <!-- 此时key值可随意,如error.code或error.exception等等。因为UserManager中throw new ErrorCodeException("user.password.error")已指定Key值 --> <!-- *********************【演示Struts的个性化异常时,所用到的异常类==》此时没有用到国际化资源文件】****************************************** --> <!-- <exception key="error.exception" type="com.jadyer.custom.AppException" handler="com.jadyer.custom.AppExceptionHandler"/> --> <!-- 其实这里指定的AppExceptionHandler.java的处理过程与Struts默认处理过程是一样的,故可省略掉handler="com.jadyer.custom.AppExceptionHandler" --> <!-- 我们查看了Struts源码中的ExceptionHandler.class的第98行,即error = new ActionMessage(ae.getKey(), ex.getMessage()); --> <!-- 可见Struts的异常处理与国际化消息文本结合了,即它肯定会new ActionMessage()出来,而且ActionMessage()里面必须得有ae.getKey(),即国际化消息文本 --> <!-- 而我们的UserManager.java中的throw new AppException("密码不正确!")根本就没有传递国际化key值,这里传的只是一个普通文本,那怎么办呢? --> <!-- 事实上,关于这个Key值,我们只要在国际化资源文件中给一个就可以了,所以我们把<exception key="">里面的error.exception配置到国际化资源文件中 --> <!-- 而在国际化资源文件中,我们应该给error.exception一个什么值呢?其实给error.exception任何值都是没有意义的,所以我们给它一个占位符{0}就可以了 --> <!-- 即error.exception={0}。而我们只需要填充这个占位符即可。比如throw new AppException("密码不正确!");那么此时"密码不正确!"便传到{0}上了 --> <!-- ****************************************************************************************************************************** -->

用于收集前台用户名和密码信息的ActionForm类

package com.jadyer.struts.form; import org.apache.struts.action.ActionForm; @SuppressWarnings("serial") public class LoginActionForm extends ActionForm { private String username; private String password; /*--两个属性的setter和getter略--*/ }

根据用户名和密码的不同进行分发处理的Action类

package com.jadyer.struts.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import com.jadyer.struts.UserManager; import com.jadyer.struts.form.LoginActionForm; public class LoginAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { LoginActionForm laf = (LoginActionForm)form; String username = laf.getUsername(); String password = laf.getPassword(); UserManager.getInstance().login(username, password); ActionMessages messages = new ActionMessages(); ActionMessage message = new ActionMessage("user.login.success",username); messages.add("loginSuccess", message); //this.saveMessages(request, messages); //request.setAttribute(Globals.MESSAGE_KEY,messages); this.saveErrors(request, messages); //request.setAttribute(Globals.ERROR_KEY,errors); return mapping.findForward("success"); } } //------------------------------------------------------------------------------------------------------- //【Struts的声明式异常】 //由于在LoginAction中没有try{}catch{}异常,那么当调用login(username,password)方法后 //可能就会出现在UserManager中设定的两个异常 //当出现这两个异常的时候,就会自动向上抛,它会抛到LoginAction中 //然后发现在LoginAction中没有对其进行拦截,那么它会继续向上抛,然后就会抛到Struts框架中 //------------------------------------------------------------------------------------------------------- //接着就会在struts-config.xml中查找是否对该异常进行的<exception/>的设置 //如果没有发现对该异常的配置,那么就会对该异常进行判断 //若该异常是IOException,则转换成IOException,若该异常是ServletException,则转换成ServletException //否则就继续向上抛。也就是说,Struts框架就不再处理了,然后就会抛到Web容器里 //如果在web.xml文件中对该异常进行了设置,那么就会按照web.xml中对该异常的处理意图进行处理 //如果在web.xml文件中也没有对该异常进行配置,那么这个异常将会直接显示在浏览器页面上 //------------------------------------------------------------------------------------------------------- //若在struts-config.xml中查找到对该异常的配置,那么Struts框架会接手处理该异常,处理过程如下 //Struts首先会创建ExceptionHandler类,然后调用该类的excute()方法,最后返回一个ActionForward //具体处理过程可以查看RequestProcessor.class中的process()方法 //然后通过process()方法就可以查看processActionPerform()方法 //接着就会发现processActionPerform()调用了processException()方法来处理异常 //然后可以在processException()方法中发现又调用了execute()方法 //接着再F3查看execute()方法代码,分析具体的异常处理方式。总之,还是多研究研究Struts的源码吧...... //------------------------------------------------------------------------------------------------------- //补充一下,ExceptionHandler类是Struts的默认处理异常的类 //对于某些异常的处理而言,Struts是满足不了我们的要求的,这时就需要个性化处理 //也就是说我们要扩展Struts,那么此时就需要扩展ExceptionHandler类 //-------------------------------------------------------------------------------------------------------

然后是用于验证用户名和密码正确与否的UserManager.java

package com.jadyer.struts; import com.jadyer.custom.AppException; public class UserManager { private static UserManager instance = new UserManager(); private UserManager() {} public static UserManager getInstance() { return instance; } // /** // * 演示Struts的声明式异常时,所用到的方法 // */ // public void login(String username, String password) { // if (!"admin".equals(username)) { // throw new UserNotFoundException(username); // } // //为了将username传递到国际化的user.not.found里的占位符中 // //所以在UserNotFoundException.java中添加一个构造方法 // if (!"jadyer".equals(password)) { // throw new PasswordErrorException(); // } // } // /** // * 演示Struts的个性化异常时,所用到的方法 // * 这里用到了国际化资源文件中的Key // */ // public void login(String username, String password) { // if (!"admin".equals(username)) { // throw new ErrorCodeException("user.not.found", username); // } // //在这里抛出的所有的异常信息,必须要关联一条国际化消息 // //但是项目有可能没有必要做国际化。具体的实现详见AppException // if (!"jadyer".equals(password)) { // throw new ErrorCodeException("user.password.error"); // } // } /** * 演示Struts的个性化异常时,所用到的方法 * 这里没有用到国际化资源文件中的Key */ public void login(String username, String password) { if (!"admin".equals(username)) { throw new AppException("用户不能找到,用户=【" + username + "】"); } if (!"jadyer".equals(password)) { throw new AppException("密码不正确!"); } } }

用于演示Struts1.x中的声明式异常处理的两个自定义异常类

package com.jadyer.struts; @SuppressWarnings("serial") public class UserNotFoundException extends RuntimeException { public UserNotFoundException(String msg) { super(msg); //只适合有一个占位符的情况下 } } /** * 用于演示Struts1.x中的声明式异常处理的两个自定义异常类 * 上面的是:当用户名不存在时,触发的异常 * 下面的是:当密码输入错误时,触发的异常 */ package com.jadyer.struts; @SuppressWarnings("serial") public class PasswordErrorException extends RuntimeException {}

用于演示Struts1.x中的个性化异常处理的两个自定义异常类

package com.jadyer.custom; @SuppressWarnings("serial") public class AppException extends RuntimeException { public AppException(String msg) { super(msg); } } /** * 用于演示Struts1.x中的个性化异常处理的两个自定义异常类 * 上面的自定义的个性化异常类,在使用的过程中,没有用到国际化资源文件中的Key * 下面...................,............,使用到了国际化资源文件中的Key */ package com.jadyer.custom; /** * 在这个类中放入错误码 * @see -------------------------------------------------------------------------------- * @see 为了在处理的时候能够方便一些,不用显式的声明和截取 * @see 所以把ErrorCodeException声明成RuntimeException,即运行期异常 * @see -------------------------------------------------------------------------------- * @see 为了处理起来方便,所以错误码的值特别建议与国际化消息文本的key相同 * @see 因为当我们抛出该异常之后,Struts框架会拿到这个错误码 * @see 然后它直接会New一个ActionMessage,于是就拿到了对应的国际化消息文本了 * @see 如果我们抛出去一个123,那么还要根据123来转换 * @see 错误码和国际化消息一样的话,就能省略转换,方便很多 * @see -------------------------------------------------------------------------------- */ @SuppressWarnings("serial") public class ErrorCodeException extends RuntimeException { //由于错误码与国际化的key相同,所以就会获取到key对应的国际化消息文本 //可能该key对应的国际化文本中有不确定个数的占位符 //所以就需要添充占位符,所以就需要增加一个对象数组 //对象数组的第0个元素就添充到第0个占位符上,第1个添充到第1个 private Object[] args; private String errorCode; /** * 国际化消息文本中没有占位符 */ public ErrorCodeException(String errorCode) { this(errorCode, null); } /** * 国际化消息文本中有一个占位符 */ public ErrorCodeException(String errorCode, Object args0) { this(errorCode, new Object[]{args0}); } /** * 国际化消息文本中有不确定个数的占位符 */ public ErrorCodeException(String errorCode, Object[] args) { this.errorCode = errorCode; this.args = args; } //只为它们提供get方法。至于赋值,则通过构造方法 //这样,通过这个异常类,就能拿到它的参数和错误码 //这个错误码,在这里就是我们的国际化消息文本 public String getErrorCode() { return errorCode; } public Object[] getArgs() { return args; } }

关于自定义的未使用到国际化资源文件中Key的AppException异常的处理类

package com.jadyer.custom; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.Globals; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ExceptionHandler; import org.apache.struts.config.ExceptionConfig; import org.apache.struts.util.ModuleException; /** * 其实我们不用写这个处理类 * 因为它和默认处理是一样的 * 它的默认处理就能够处理了 * 写这个类的目的是了解了解 */ public class AppExceptionHandler extends ExceptionHandler { public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { if (!(ex instanceof AppException)) { return super.execute(ex, ae, mapping, formInstance, request, response); } ActionForward forward = null; ActionMessage error = null; String property = null; // Build the forward from the exception mapping if it exists or from the form input if (ae.getPath() != null) { forward = new ActionForward(ae.getPath()); } else { forward = mapping.getInputForward(); } // Figure out the error if (ex instanceof ModuleException) { error = ((ModuleException) ex).getActionMessage(); property = ((ModuleException) ex).getProperty(); } else { AppException appe = (AppException) ex; error = new ActionMessage(ae.getKey(), appe.getMessage()); property = error.getKey(); // error = new ActionMessage(ae.getKey(), ex.getMessage()); // property = error.getKey(); } this.logException(ex); // Store the exception request.setAttribute(Globals.EXCEPTION_KEY, ex); this.storeException(request, property, error, forward, ae.getScope()); return forward; } }

关于自定义的使用到了国际化资源文件中key的ErrorCodeException异常的处理类

package com.jadyer.custom; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.Globals; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ExceptionHandler; import org.apache.struts.config.ExceptionConfig; import org.apache.struts.util.ModuleException; /** * 个性化异常处理类 * 该类只处理ErrorCodeException异常 */ public class ErrorCodeExceptionHandler extends ExceptionHandler { // 复写ExceptionHandler类的execute()方法 public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { // 容错处理。注意需要return返回ActionForward,否则程序还会继续向下执行的 // 即如果该异常不是ErrorCodeException异常,那么我们就不再处理该异常了,而是转交给Struts的默认异常处理类 if (!(ex instanceof ErrorCodeException)) { return super.execute(ex, ae, mapping, formInstance, request, response); } ActionForward forward = null; ActionMessage error = null; String property = null; // Build the forward from the exception mapping if it exists or from the form input // ae即参数中的ExceptionConfig,即代表struts-config.xml中的<exception/>标签中的配置信息 if (ae.getPath() != null) { forward = new ActionForward(ae.getPath()); } else { forward = mapping.getInputForward(); } // Figure out the error if (ex instanceof ModuleException) { error = ((ModuleException) ex).getActionMessage(); property = ((ModuleException) ex).getProperty(); } else { // 通过UserManager中的throw new ErrorCodeException("user.not.found",username) // 说明我们通过ErrorCodeException已经把errorCode和它的占位符携带过来了 // 所以在我们定义的异常处理类中就可以获取到errorCode和它的占位符 // 由于我们传入的是国际化消息文本中的key,所以此时其实已经拿到了国际化消息文本 ErrorCodeException ece = (ErrorCodeException) ex; String errorCode = ece.getErrorCode(); Object[] args = ece.getArgs(); // error = new ActionMessage(ae.getKey(), ex.getMessage()); // property = error.getKey(); // 这是Struts的ExceptionHandler类的默认处理 // 但它已经满足不了我们的要求了,所以要把它注释掉,然后手工定义我们的处理方式 error = new ActionMessage(errorCode, args); property = error.getKey(); } this.logException(ex); // Store the exception request.setAttribute(Globals.EXCEPTION_KEY, ex); this.storeException(request, property, error, forward, ae.getScope()); return forward; } }

最后是使用到的国际化资源文件MessageResources.properties

#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # -- standard errors -- error.exception = {0} errors.footer = </UL> errors.header = <UL> errors.prefix = <LI><font color="red"><strong> errors.suffix = </strong></font></LI> user.login.success = {0},Login Success user.not.found = User Not Found,UserName=[{0}] user.password.error = Password is Error #下面是MessageResources_zh_CN.properties文件的内容 error.exception = {0} errors.footer = </UL> errors.header = <UL> errors.prefix = <LI><font color="red"><strong> errors.suffix = </strong></font></LI> user.login.success = {0},/u767B/u5F55/u6210/u529F user.not.found = /u7528/u6237/u4E0D/u80FD/u627E/u5230/uFF0C/u7528/u6237/u540D/u79F0/=[{0}] user.password.error = /u5BC6/u7801/u9519/u8BEF

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值