struts处理异常

编程式异常:

1、概念:在Action中调用业务逻辑层对象的方法时,用try{ }catch的方式来截获异常之后,手工对异常进行处理

2、在哪里处理?
在Action里的excute里处理

3、处理过程:
1、截获异常
2、创建消息文本对象
3、把消息文本对象放到ActionMessages里
4、把ActionMessages放到request里,属性名为Globals.ERROR_KEY

声明式异常:

概念:在action中不处理异常,把异常交给struts处理
processActionPerform调用action的excute方法
我们需要在配置文件中指示struts如何处理这些被抛出的异常,使用元素来定义自动异常处理

在struts-config.xml文件中配置<exeception/>标签

<action path="/login"
                  type="com.bjsxt.struts.LoginAction"
                  name="loginForm"
                  scope="request"
                  validate="false"
                  input="/login.jsp"
         >    
         <!--
     <exception key="user.not.found"  type="com.bjsxt.struts.UserNotFoundException"  path="/login_error.jsp"/>
     <exception key="user.password.error"  type="com.bjsxt.struts.PasswordErrorException"  path="/login_error.jsp"/>
          -->
              <forward name="success"  path="/login_success.jsp"/>
              <forward name="error" path="/login.jsp"/>
 </action>

<exception/>元素的配置,指示了struts如何处理异常的方式
在通常的情况下,我们得到异常以后,需要将页面导航到一个错误提示的页面,提示错误信息

tomcat一启动为<exception />标签创建了ExceptionConfig,
ExceptionConfig:封装配置信息里的exception标签,有5个属性,(path,scope,handle可以省略)
把ExceptionConfig封装到一个map里,这个map叫Exceptions,这个map的key是type(异常对象类型)
<exception/>元素配置的关键属性是:
key – 即这个异常所对应的错误提示消息文本的key,这个key的值,需要在资源属性文件中进行定义(国际化资源文件的key)
type – 即定义需要处理哪种类型的Exception( 异常类型)
path – 定义一旦出现异常,需要转向哪个页面来进行提示,如果不定义path属性,默认情况下,将使用Action配置中的input属性的值来作为转向的页面(指定在哪个页面处理异常信息)
scope:可以取值request和session,默认为request
handler:异常的处理类,struts默认采用org.apache.struts.action.ExceptionHandler,如果做个性化的异常处理可以继承此类覆写相应的方法

登录的业务层

public void login(String username, String password) {
      if (!"admin".equals(username)) {
           throw new UserNotFoundException(username);
      }
      if (!"admin".equals(password)) {
           throw new PasswordErrorException();
       }
  }

struts源码

protected ActionForward
        processActionPerform(HttpServletRequest request,
                             HttpServletResponse response,
                             Action action,
                             ActionForm form,
                             ActionMapping mapping)
        throws IOException, ServletException {
        try {
            return (action.execute(mapping, form, request, response));
        } catch (Exception e) {
            return (processException(request, response,
                                     e, form, mapping));
        }
    }
------------------------------------------------------------------------------
protected ActionForward processException(HttpServletRequest request,
                                             HttpServletResponse response,
                                             Exception exception,
                                             ActionForm form,
                                             ActionMapping mapping)
        throws IOException, ServletException {
        // Is there a defined handler for this exception?
        ExceptionConfig config = mapping.findException(exception.getClass());

---------------------------------------------------------------------
try {
            ExceptionHandler handler = (ExceptionHandler)
            RequestUtils.applicationInstance(config.getHandler());
            return (handler.execute(exception, config, mapping, form,
                                    request, response));
        } catch (Exception e) {
            throw new ServletException(e);
        }

1、通过抛出的异常对象找到异常类(通过反射),然后到ActionMapping里找到exceptions这个map,然后通过key(异常对象的类型)找到ExceptionConfig
2、通过ExceptionConfig拿到handle属性,

 public ActionForward execute(
        Exception ex,  //抛出的异常对象
        ExceptionConfig ae,   //配置信息里的Exception标签
        ActionMapping mapping,   //这个请求的配置信息
        ActionForm formInstance,   
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException {
        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 {
            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;
    }


protected void storeException(
        HttpServletRequest request,
        String property,
        ActionMessage error,
        ActionForward forward,
        String scope) {
        ActionMessages errors = new ActionMessages();
        errors.add(property, error);
        if ("request".equals(scope)) {
            request.setAttribute(Globals.ERROR_KEY, errors);
        } else {
            request.getSession().setAttribute(Globals.ERROR_KEY, errors);
        }
    }

1、先到exception标签里找到path属性,如果存在就创建ActionForward作为转向,如果不存在就在ActionMapping里找到input属性
2、创建国际化文本对象
3、storeException:把ActionMessage存放到ActionMessages,然后把ActionMessages设置到request里
4、返回到调用这个异常的方法ActionForward,在本例子中是/login_error.jsp

struts处理异常流程
1、用户名不匹配,就创建UserNotFoundException对象,并且通过有参的构造方法调用父类的super把异常信息设置给异常对象的message属性,然后通过throw把创建的异常对象抛出给action的excute方法,action的excute方法再抛给processActionPerform
2、在processActionPerform将异常拦截,然后调用processException方法
3、在processException方法到配置信息里找exceptionConfig,
4、通过ExceptionConfig拿到handle属性(通过反射创建出ExceptionHandler对象,然后执行excute方法)
5、在execute方法里通过ExceptionConfig找path,如果找到了,就用path创建ActionForward,如果没找到,就到ActionMapping里找input属性,都没找到就出错
6、创建国际化文本对象ActionMessage,第一个参数是Exception标签里的key,第二个参数填充符(异常对象信息)
7、把ActionMessage存放到ActionMessages,然后把ActionMessages设置到request里Globals.ERROR_KEY
8、把ActionForward回传给调用方法,struts通过调用processForwardConfig对forward解析,进入到错误页面

修饰标签,每一行用红色代表

errors.header=<UL>
errors.prefix=<LI><font color="red">
errors.suffix=</font></LI>
errors.footer=</UL>

二、用一个异常类,处理多个异常信息

全局exception配置

<global-exceptions>
     <!--
              <exception key="user.not.found" type="com.bjsxt.struts.UserNotFoundException" path="/login_error.jsp"/>
              <exception key="user.password.error" type="com.bjsxt.struts.PasswordErrorException" path="/login_error.jsp"/>
      -->

      <!--
         <exception key="user.not.found" type="com.bjsxt.struts.UserNotFoundException" handler="org.apache.struts.action.ExceptionHandler"/>
         <exception key="user.password.error" type="com.bjsxt.struts.PasswordErrorException" handler="org.apache.struts.action.ExceptionHandler"/>
      -->

      <!--
      <exception key="error.exception" type="com.bjsxt.struts.ErrorCodeException" handler="com.bjsxt.struts.ErrorCodeExceptionHandler"/>
       -->
       <!--
       <exception key="error.exception" type="com.bjsxt.struts.AppException" handler="com.bjsxt.struts.AppExceptionHandler"/>
        -->   

       <exception key="error.exception" type="com.bjsxt.struts.AppException"/>
     </global-exceptions>

自定义一个异常类,继承RuntimeException

public class ErrorCodeException extends RuntimeException {

     private String errorCode;

     private Object[] args;

     public ErrorCodeException(String errorCode) {
         this(errorCode, null);
     }
     //两个属性,一个是国际化资源的key,一个是动态填充符
     public ErrorCodeException(String errorCode, Object args0) {
         this(errorCode, new Object[]{args0});
     }

     public ErrorCodeException(String errorCode, Object[] args) {
         this.errorCode = errorCode;
         this.args = args;
     }

     public String getErrorCode() {
         return errorCode;
     }
     public Object[] getArgs() {
         return args;
     }
}

自定义ErrorCodeExceptionHandler 继承 ExceptionHandler

public class ErrorCodeExceptionHandler extends ExceptionHandler {
    public ActionForward execute(
            Exception ex,
            ExceptionConfig ae,
            ActionMapping mapping,
            ActionForm formInstance,
            HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException {

        //如果这个异常对象不是ErrorCodeException就调用父类
         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
            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 {
              ErrorCodeException ece = (ErrorCodeException)ex;

              String errorCode = ece.getErrorCode();
              Object[] args = ece.getArgs();
              error = new ActionMessage(errorCode, args);
              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;
        }
}

先在请求对应的配置信息里找,没找到再到全局配置里找

 public ExceptionConfig findException(Class type) {
        // Check through the entire superclass hierarchy as needed
        ExceptionConfig config = null;
        while (true) {
            // Check for a locally defined handler
            String name = type.getName();
            config = findExceptionConfig(name);
            if (config != null) {
                return (config);
            }
            // Check for a globally defined handler
            config = getModuleConfig().findExceptionConfig(name);
            if (config != null) {
                return (config);
            }
            // Loop again for our superclass (if any)
            type = type.getSuperclass();
            if (type == null) {
                break;
            }
        }
        return (null); // No handler has been configured
    }

登录的业务层

public void login(String username, String password) {
      if (!"admin".equals(username)) {
           throw new ErrorCodeException("user.not.found", username);
      }
       if (!"admin".equals(password)) {
          throw new ErrorCodeException("user.password.error");
      }
   }

步骤:
1、自定义一个异常类,继承RuntimeException
2、创建异常对象,往ErrorCodeException里设置信息,国际化资源文件的key和动态填充符
3、全局配置,配置自定义的handle
4、覆写ErrorCodeExceptionHandler 继承 ExceptionHandler

优点:
1、用一个异常类处理多个异常对象
2、配置简单

缺点:自己覆写Exception

三、用一个类处理所有的异常,不用覆写 ErrorCodeExceptionHandler

第一种:
优点:
缺点:只能写一个动态填充

第二种:
优点:
缺点:需要覆写

第三种方案:
优点:用一个类处理多个异常对象
2、只配全局exception
3、没有覆写ExceptionHandle
4、可以显示多个动态填充

缺点:无法国际化

猜你喜欢

转载自blog.csdn.net/Pluto__lxh/article/details/82215573