客户端和服务端对异常的不同处理态度【JFinal】

服务端后台管理这种如果代码中抛出异常,其Tx事务能起作用,但是在客户端与服务端交互的时候很多都是通过JSON或者XML格式,为了用户体验,成功的话就正常返回,不成功也应该给出失败的信息,而不是直接报505这种错误,那么我们就需要在服务端自己处理掉异常,这样Tx就认为你的代码自己能处理异常,它就不起作用了。我回去查看了Tx的源码,它的原理就是在操作之前设置非自动提交,然后捕获异常,有异常就回滚,没有异常就提交。我们在写的时候也可以参照它的实现,相当于将我们处理的异常和数据库的处理异常合并。【基于JFinal】!!在这个Tx的源码中,当他抓到RuntimeException,它就继续把这个异常往外抛,否者就抛出ActiveRecordException(t),所以我们如果在我们的源码中应用了Tx,我们应该应用下面经过改造的Tx--》TxDoneEx,异常合并处理,而不要往外抛,是controller方法中还是可以自己处理异常,然后还需要往外抛,以TxDoneEx 能回滚事务。

将下面的所有处理异常的地方都改为我们自己处理,而不是往外抛。

public class TxDoneEx implements Interceptor {
	
	public static Config getConfigWithTxConfig(Invocation inv) {
		TxConfig txConfig = inv.getMethod().getAnnotation(TxConfig.class);
		if (txConfig == null)
			txConfig = inv.getTarget().getClass().getAnnotation(TxConfig.class);
		
		if (txConfig != null) {
			Config config = DbKit.getConfig(txConfig.value());
			if (config == null)
				throw new RuntimeException("Config not found with TxConfig: " + txConfig.value());
			return config;
		}
		return null;
	}
	
	protected int getTransactionLevel(Config config) {
		return config.getTransactionLevel();
	}
	
	public void intercept(Invocation inv) {
		Config config = getConfigWithTxConfig(inv);
		if (config == null)
			config = DbKit.getConfig();
		
		Connection conn = config.getThreadLocalConnection();
		if (conn != null) {	// Nested transaction support
			try {
				if (conn.getTransactionIsolation() < getTransactionLevel(config))
					conn.setTransactionIsolation(getTransactionLevel(config));
				inv.invoke();
				return ;
			} catch (SQLException e) {
				throw new ActiveRecordException(e);
			}
		}
		
		Boolean autoCommit = null;
		try {
			conn = config.getConnection();
			autoCommit = conn.getAutoCommit();
			config.setThreadLocalConnection(conn);
			conn.setTransactionIsolation(getTransactionLevel(config));	// conn.setTransactionIsolation(transactionLevel);
			conn.setAutoCommit(false);
			inv.invoke();
			conn.commit();
		} catch (NestedTransactionHelpException e) {
			if (conn != null) try {conn.rollback();} catch (Exception e1) {e1.printStackTrace();}
		} catch (Throwable t) {
			if (conn != null) try {conn.rollback();} catch (Exception e1) {e1.printStackTrace();}
			throw t instanceof RuntimeException ? (RuntimeException)t : new ActiveRecordException(t);
		}
		finally {
			try {
				if (conn != null) {
					if (autoCommit != null)
						conn.setAutoCommit(autoCommit);
					conn.close();
				}
			} catch (Throwable t) {
				t.printStackTrace();	// can not throw exception here, otherwise the more important exception in previous catch block can not be thrown
			}
			finally {
				config.removeThreadLocalConnection();	// prevent memory leak
			}
		}
	}
}




你可能感兴趣的:(客户端和服务端对异常的不同处理态度【JFinal】)