学习Struts框架系列(三):声明式异常处理

时间:2022-09-28 20:56:53

在Struts1.X的版本中加入了对异常的处理Exception Handler,有了它我们可以不使用try/catch捕获异常,一旦出现了我们已经定义的异常,那么就会转到相应的页面,并且携带异常信息,自动性增强。

Struts框架提供了默认的异常处理org.apache.struts.action.ExceptionHandler,它的execute()方法负责处理异常,在需要实现自定义处理时重写该方法。可以在配置文件中定义由谁来处理Action类中掷出的某种异常。

处理异常的流程

struts的控制器负责捕获各种异常,包括控制器运行中本身抛出的异常,以及调用模型的业务方法时抛出的异常。

当struts的控制器捕获到异常后,在异常处理代码块中,创建描述信息的actionMessage对象,并把它保存在特定范围(配置文件中的scope)。

在jsp中使用<html:errors/>标签,可以检索到特定范围内的actionMessages对象。

通过这个完整的代码示例,你将知道如何使用ExceptionHandler统一处理异常

struts配置文件

<global-exceptions>
<!-- 当遇到 type为java.lang.Exception异常时,使用com.bjsxt.oa.web.SystemExceptionHandler进行处理-->
<exception
key="errors.detail"
type="java.lang.Exception"
path="/common/exception.jsp"
scope="request"
handler="com.bjsxt.oa.web.SystemExceptionHandler"
></exception>
</global-exceptions>

key – 即这个异常所对应的错误提示消息文本的key,这个key的值,需要在资源属性文件中进行定义

type – 即定义需要处理哪种类型的Exception

path – 定义一旦出现异常,需要转向哪个页面来进行提示,如果不定义path属性,默认情况下,将使用Action配置中的input属性的值来作为转向的页面

局部和全局

handler -负责异常处理的类,缺省为org.apache.struts.action.Exceptionhandler.java,如果做个性化的异常处理可以继承此类覆盖execute方法

SystemExceptionHandler

使用SystemExceptionHandler统一处理SystemException异常

SystemExceptionHandler是自定义的ExceptionHandler类,重写了execute方法,实现自定义处理。

importcom.bjsxt.oa.manager.SystemException;

public classSystemExceptionHandler extends ExceptionHandler {

//日志记录对象
//commons-log类型接口,log4j实现
privatestatic Log logger = LogFactory.getLog(SystemExceptionHandler.class); /**
* 处理SystemException异常
*/
@Override
publicActionForward execute(
Exceptionex,
ExceptionConfigae,
ActionMappingmapping,
ActionFormformInstance,
HttpServletRequestrequest,
HttpServletResponseresponse) throws ServletException { //ExceptionConfig 和配置文件的exception标签信息对应
//ActionMapping和请求的action标签信息对应 //构造ActionForward对象
ActionForwardforward = null;
if(ae.getPath()!= null){
forward= new ActionForward(ae.getPath());
}else{
forward= mapping.getInputForward();
} logger.debug("出现异常",ex); //ex.printStackTrace(); //只对SystemException异常进行处理
//构造ActionMessage对象
if(exinstanceof SystemException){
SystemExceptionse = (SystemException)ex; //取出key值
Stringkey = se.getKey(); ActionMessageerror = null;
if(key == null){
error= new ActionMessage(ae.getKey(),se.getMessage());
}else{
if(se.getValues()!= null){
error= new ActionMessage(key,se.getValues());
}else{
error= new ActionMessage(key);
}
} this.storeException(request,key, error, forward, ae.getScope()); returnforward;
} returnsuper.execute(ex, ae, mapping, formInstance, request, response);
} }

SystemException

自定义异常类

public classSystemException extends RuntimeException {

//异常代码
privateString key; privateObject[] values; publicSystemException() {
super();
} publicSystemException(String message) {
super(message);
} publicSystemException(Throwable throwable) {
super(throwable);
}
publicSystemException(String message, Throwable throwable) {
super(message,throwable);
} publicSystemException(String message,String key){
super(message);
this.key= key;
} publicSystemException(String message,String key,Object value){
super(message);
this.key= key;
this.values= new Object[]{value};
} publicSystemException(String message,String key,Object[] values){
super(message);
this.key= key;
this.values= values;
} publicString getKey() {
returnkey;
} publicObject[] getValues() {
returnvalues;
} }

OrgManagerImpl

在这里抛出异常,异常会一直抛到Action,直到被struts控制器捕获。

publicvoid delOrg(int orgId) {

Orgnizationorg = (Orgnization)getHibernateTemplate().load(Orgnization.class, orgId);

//先判断是否存在子机构,如果存在子机构,则不允许删除
if(org.getChildren().size()> 0){
// 使用多种情况的异常信息:国际化、自定义
thrownewSystemException("存在子机构,不允许删除","exception.org.del",org.getId());
// thrownew SystemException("存在子机构,不允许删除");
} getHibernateTemplate().delete(
org
);
}

MessageResources.properties

国际化资源文件

exception.org.del=Can'tDel Orgnization,id is {0}\!

小结

声明式异常,在代码中只进行抛异常就够了,捕获异常的事交给了ExceptionHandler类,省事多了。因为每一个异常类,对应的就需要有一个Handler类处理,所以这个异常类的粒度不能太细。

和编程式异常相比,编程式异常就比较灵活了,在action中可以针对manager提供的异常情况再做处理,进而向页面显示出合理的友好的提示信息,但因为在action中作为异常的处理终点,导致action类会比较庞大而且代码可读性下降。 

总之,处理异常的这两种方式,一个粒度粗些,一个粒度细些,酌情处理就是了。