在Struts框架中,对于异常的处理主要有两种机制:编程式和声明式。
一、编程式异常处理:
* 捕获异常
* 创建相应的异常消息
* 传递异常消息
* 到相应的页面处理异常
如在Action中:
try{
......
}catch(UserNotFoundException unf){
//创建国际化文本消息
ActionMessage message = new ActionMessage("user.login.userNameNotFound",username);
messages.add("error1", message);
//传递国际化文本消息
this.saveErrors(request, messages);
}catch(PasswordErrorException pee){
//创建国际化文本
ActionMessage message = new ActionMessage("user.login.passwordError");
messages.add("error2",message);
//传递国际化文本
this.saveErrors(request, messages);
}
然后再到页面处理:<html:errors/>
二、声明式异常处理(即用<exception/>标签配置):
* 在相应的action配置中添加<exception>配置(注意:要放在<forward>前面,这是由DTD决定的)
<action path="/login"
type="cn.huan.struts.LoginAction"
name="loginForm"
scope="request"
input="/login.jsp"
>
<exception type="cn.huan.struts.UserNotFoundException" key="user.login.userNameNotFound" path="/login_error.jsp"/>
<exception type="cn.huan.struts.PasswordErrorException" key="user.login.passwordError" path="/login_error.jsp"/>
<forward name="success" path="/login_success.jsp"/>
<forward name="error" path="/login_error.jsp"/>
</action>
其中<exception>的type指定该Exception的类绝对路径(这里是我自己定义的两个RuntimeException),key指定properties资源文件中的key值,path指定异常处理页面(没配该属性时会到input页面处理,因为默认异常处理类ExceptionHandler会先判断getPath是否有值,非空就new一个该getPath的ActionForward,为空就设置为mapping.getInputForward的值)
* 若多个action都需配同一个exception就可以将其设为全局exception来配置,mapping.findException方法会先到action中找局部exception,若没有就会找全局exception:
<global-exceptions>
<exception type="cn.huan.struts.UserNotFoundException" key="user.login.userNameNotFound"/>
<exception type="cn.huan.struts.PasswordErrorException" key="user.login.passwordError"/>
</global-exceptions>
若没配path就会根据各action中的input属性配置处理异常
* 页面显示和编码方式一样用<html:messages/>标签或<html:errors/>标签
另、自定义个性化异常
若想把资源文件中配的异常信息都用一个异常来处理,就可自定义异常,并在struts-config.xml中配一处就ok….
* 自定义异常,如 ErrorCodeException.java:
package cn.huan.struts;
/**
*
* @author 刘银环
*
*/
public class ErrorCodeException extends RuntimeException {
//错误码
private String errorCode;
//栈位符消息
private Object[] args;
/**
* 构造函数一,根据错误码构造
* @param errorCode:错误码
*/
public ErrorCodeException(String errorCode){
this(errorCode,null);
}
/**
package cn.huan.struts;
/**
*
* @author 刘银环
*
*/
public class ErrorCodeException extends RuntimeException {
//错误码
private String errorCode;
//栈位符消息
private Object[] args;
/**
* 构造函数一,根据错误码构造
* @param errorCode:错误码
*/
public ErrorCodeException(String errorCode){
this(errorCode,null);
}
/**
* 构造函数二,根据错误码和单个栈位符消息
* @param errorCode:错误码
* @param args:单个栈位符消息
*/
public ErrorCodeException(String errorCode,Object args){
this(errorCode,new Object[]{args});
}
/**
* 构造函数三,根据错误码和多个栈位符消息
* @param errorCode:错误码
* @param args:多个栈位符消息
*/
public ErrorCodeException(String errorCode,Object[] args){
this.errorCode = errorCode;
this.args = args;
}
/**
* @return the errorCode
*/
public String getErrorCode() {
return errorCode;
}
/**
* @return the args
*/
public Object[] getArgs() {
return args;
}
}
* 自定义异常处理类继承ExceptionHandler,只需重写execute方法的部分代码,如 ErrorCodeExceptionHandler.java:
public ActionForward execute(Exception ex, ExceptionConfig ae,
ActionMapping mapping, ActionForm formInstance,
HttpServletRequest request, HttpServletResponse response)
throws ServletException {
LOG.debug("ExceptionHandler executing for exception " + ex);
ActionForward forward;
ActionMessage error;
String property;
//如果不是自定义的ErrorCodeException,就抛给默认的ExceptionHandler处理
if(!(ex instanceof ErrorCodeException)){
return super.execute(ex, ae, mapping, formInstance, request, response);
}
// 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());
if (!response.isCommitted()) {
return forward;
}
LOG.debug("Response is already committed, so forwarding will not work."
+ " Attempt alternate handling.");
if (!silent(ae)) {
handleCommittedResponse(ex, ae, mapping, formInstance, request,
response, forward);
} else {
LOG.warn("ExceptionHandler configured with " + SILENT_IF_COMMITTED
+ " and response is committed.", ex);
}
return null;
}
(上面只给出了重写的execute方法)
* 配置,
<global-exceptions>
<exception key="error.exception" type="cn.huan.struts.ErrorCodeException" handler="cn.huan.struts.ErrorCodeExceptionHandler"/>
</global-exceptions>
上面的key指定properties资源文件中的key值,type指定异常类,handler指定异常的处理类(若没给出就会采用默认的ExceptionHandler)
* 使用:
if(!"admin".equals(username)){
throw new ErrorCodeException("user.login.userNameNotFound",username);
}
if(!"admin".equals(password)){
throw new ErrorCodeException("user.login.passwordError");
}
当然,这种自定义的异常也能处理没有配在资源文件中的异常信息..