论坛首页 Java企业应用论坛

基于Spring和hibernate的灵活的异常处理办法

浏览 2453 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-12  
在spring,hibernate中异常的处理都交给了spring框架,在hibernate只需要写很少的代码就可以实现异常的控制。
在单元测试代码中:
public final void testFindFunctionById() {
logger.debug("testFindFunctionById");
long l1=System.currentTimeMillis();
String id="4";
Function function=BeanFactory.getInstance().getRightDelegate().findFunctionById(id, state);
    long l2=System.currentTimeMillis();
    System.out.println("function.getId = "+function.getId());
    System.out.println("function.getName = "+function.getName());
    System.out.println("function.getProtectFunction = "+function.getProtectFunction());
    System.out.println("--------------finish----------------");  
    System.out.println("一共用时为 :  "+(l2-l1));   
}

在delegate中接受信息:
public Function findFunctionById(String id, IState state) {
if (DelegateUtil.isNullParam(id, "id", state)) {
return null;
}
Request req = new Request();
req.setServiceName(ServiceConsts.FindFunctionByIdProcessor);
req.setValue("id", id);
try {
Response resp = getDelegate().execute(req);
DelegateUtil.setIState(state, resp);
Function function = (Function) resp.getValue("function");
DelegateUtil.setIState(state, resp);
return function;
} catch (Exception e) {
DelegateUtil.handleException(e, "findFunctionById", state);
return null;
}
}
在delegate中首先对参数做一般的空指针检查,如下面的代码
public static boolean isNullParam(Object paramObject, String paramName,
IState state)
{
if (paramObject == null) {
logger.error("Parameter " + paramName + " is null;");
state.setErrCode(ErrorCode.PARAMETER_ERROR);
return true;
}
return false;
}
如果传值是null的话,在state中设置ErrorCode.PARAMETER_ERROR参数直接返回给客户端,客户端根据不同的ErrorCode可以知道问题的所在,并作出相应的操作。
   然后生成一个Request,封装了这次请求的参数,如ServiceName和values。请求分发到相应的service,如FindFunctionByIdProcessor。Service再将请求分发到service下面的command,command代码如下:
public class FindFunctionById extends Command
{
private FunctionDao dao;
public void setDao(FunctionDao dao) {
this.dao = dao;
}
public void execute(Map params, Map response) throws Exception
{
response.put("function",(Function)dao.getById(Function.class, (String) params.get("id")));
}
……
}
在command中把参数接下来调用dao的方法,并把结果放在response中。在delegate就可以在response中取得结果。
Dao的代码如下:
public Object getById(Class c, Serializable id) {
return getHibernateTemplate().get(c, id);
}
在dao中只是调用了spring的类。这个调用流程没有涉及到异常的捕捉。那他是在哪里处理的呢?看下面的代码(习惯了以代码说话了,呵呵)
public class SequenceProcessor extends BaseProcessor {
private static Logger logger=Logger.getLogger(SequenceProcessor.class);
    public boolean supports(Component component) {
        return (component instanceof Command);
    }
    public void doActivities(Request request,Response resp) throws Exception {
        logger.info("SequenceProcessor 流程开始 <-- "+getBeanName() );
Map response = resp.getValues();
Map params = request.getValues();
        List activities = getActivities();
        for (Iterator it = activities.iterator(); it.hasNext();) {
            Component component = (Component) it.next();
            logger.info("活动 : " + component.getBeanName());
            try {
            component.init("");
            component.execute(params, response);
            component.fini();
            } catch (Throwable th) {
                ErrorHandler errorHandler = component.getErrorHandler();
                if (errorHandler == null) {
                    logger.info("no Errorhandler for Command "+component.getBeanName() +", run processor Errorhandler and abort Command ");
                    ErrorHandler processorerrorHandler=getErrorHandler();
                    if(processorerrorHandler == null){
                    logger.info("no error handler for this processor, run defaultErrorHandler and abort processor ");
                    //执行全局的default ErrorHandler;
                    ErrorHandler defaultErrorHandler=((ErrorHandler)ContextServiceLocator.getInstance().getBean("defaultErrorHandler"));
                    if(defaultErrorHandler!=null)
                      defaultErrorHandler.handleError(resp, th);
                    else{
                    logger.info("no default errorHandler for this invoke process, abort!!");
                    }
                    }else{
                        // 执行processor级的ErrorHandler;
                    logger.info("run processor errorHandler and continue");
                    processorerrorHandler.handleError(resp, th);
                    }
                 
                } else {
                    logger.info("run Command Errorhandler and continue");
//                  执行Component级的ErrorHandler;
                    errorHandler.handleError(resp, th);
                }
            }
 
        }
        logger.info(" SequenceProcessor 流程结束 -->");
    }
}
在service中发生了异常有3个地方可以做切入点来做处理。Command级别,service级别和全局的错误处理器。如果在command中发生异常,首先查找Command级别的错误处理器,找不到则找service级别的错误处理器,再找不到就找全局的错误处理器,什么也没有找到异常则继续抛下去一直到客户端。如下面配置文件所示:
<bean id="activity2"
class="org.artemis.workflow.command.Activity2">
<property name="errorHandler">
<ref bean="defaultErrorHandler" />
</property>
</bean>
<!-- error handler -->
<bean id="defaultErrorHandler"
class="com.gsta.eshore.framework.jcf.JCFErrorHandler" />
在activity2中发生异常就会查找defaultErrorHandler来做相应的处理。
public class JCFErrorHandler implements ErrorHandler {

    private String beanName;
    private static Logger logger=Logger.getLogger(JCFErrorHandler.class);

    public void handleError(Response resp, Throwable th) throws Exception{
    if (th instanceof ClientException) {
            logger.error("JCFErrorHandler is dealing with ClientException errorCode is "+((ClientException)th).getErrorCode(),th);
resp.setReturnCode(Response.APPLICATION_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.BUSINESS_ERROR);
        throw (ClientException)th;
    }
    else if (th instanceof GoOnException) {
        logger.error("JCFErrorHandler is dealing with GoOnException", th);
        } else if(th instanceof JCFException){
            logger.error("JCFErrorHandler is dealing with JCFException errorCode is "+((JCFException)th).getErrorCode(),th);
resp.setReturnCode(Response.APPLICATION_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.JCF_ERROR);
        throw (JCFException)th;
        } else if(th instanceof RemoteException){
            logger.error("JCFErrorHandler is dealing with RemoteException",th);
resp.setReturnCode(Response.SYSTEM_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.SYSTEM_ERROR);
        throw (RemoteException)th;
        } else if(th instanceof EJBException){
            logger.error("JCFErrorHandler is dealing with EJBException",th);
resp.setReturnCode(Response.SYSTEM_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.CALL_EJB_ERROR);
        throw (EJBException)th;
       } else if(th instanceof NullPointerException){
        logger.error("JCFErrorHandler is dealing with RemoteException",th);
resp.setReturnCode(Response.APPLICATION_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.NULLPOINT_ERROR);
    throw (NullPointerException)th;
    }
        else{
            logger.error("JCFErrorHandler is dealing with Exception",th);
resp.setReturnCode(Response.APPLICATION_LEVEL_ERROR);
resp.getState().setErrCode(ErrorCode.SYSTEM_ERROR);
if(th instanceof Exception)
               throw (Exception)th;
        }
    }
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}
可以为每一个command或者service定制不同的错误处理器。针对不同的异常来设置不同的errorCode,同时后端的异常不会影响到客户端的操作。
   总结:把异常处理抽取出来,代码进一步简化。如果有什么疑问或者good idea欢迎给我发邮件:gmhwq@126.com
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics