2

我最近继承了一些遗留代码,这些代码大量使用内部类来实现线程。这些内部类使当前JFrame代码成为整体,因此我正在重构代码以利用SwingWorker该类。

我的SwingWorker班级对 Web 服务进行了多次 API 调用,然后返回结果。由于这是异步的,这显然最好在线程内完成。目前,Web 服务的工作方式需要一些身份验证调用来验证请求。这些调用显然会返回错误。SwingWorker如果这些 Web 服务调用未通过身份验证,我想做的是从内部抛出一个自定义异常。使用标准Future模式,我的代码类似于以下内容:

SwingWorker(后台线程)

@Override
protected String doInBackground() throws Exception {
    if (!authenticationClient.authenticate(userid)) {
        throw new PlaceOrderException("Failed to authenticate client");
    }

    return orderClient.placeOrder( ... );
}

主 GUI(EDT 线程)

// On the EDT
PlaceOrderWorker placeOrderWorker = new PlaceOrderWorker( ... ) {
    // This method is invoked when the worker is finished its task
    @Override
    protected void done(){
        try {
            String orderID = get();

            // Update some GUI elements using the orderID

        } catch(PlaceOrderException e) {
            JOptionPane.showMessageDialog(this, "Please review your order", e.getMessage(), JOptionPane.ERROR_MESSAGE, null);
        } catch (Exception e) {
            LOGGER.error("Error placing order", e);
        }
    }
}

错误发生在该行:

catch(PlaceOrderException e) {
    JOptionPane.showMessageDialog(this, "Please review your order", e.getMessage(), JOptionPane.ERROR_MESSAGE, null);
} 

正如 Java 声称的那样,这个异常永远不会被抛出。

exception PlaceOrderException is never thrown in body of corresponding try statement

现在我知道调用get会导致异常从线程中重新抛出 - 它可以抛出一个PlaceOrderException. 我怎样才能捕捉到这个特定的异常?我这样构造我的代码的原因是有许多异常可以在后台线程中抛出,我希望用户通过JDialog. 我在主 GUI 类中声明该done方法的原因是我需要JDialog从 EDT 线程中实例化 s。这让我有一些很好的解耦。

任何人都知道我使用 using 捕获此特定异常的方法instanceof吗?或者你能推荐一个更好的模式来使用吗?也许SwingWorker是错误的选择?

4

1 回答 1

6

抓住ExecutionException并调查其原因:

    try {
        String orderID = get();

        // Update some GUI elements using the orderID

    } catch(ExecutionException e) {
        Throwable cause = e.getCause( );
        if ( cause instanceof PlaceOrderException )
        {
            JOptionPane.showMessageDialog(
              this,
              "Please review your order",
              cause.getMessage(),
              JOptionPane.ERROR_MESSAGE,
              null
            );
        }
        else
        {
          LOGGER.error("Error placing order", e);
        }
    } catch (Exception e) {
        LOGGER.error("Error placing order", e);
    }
于 2012-11-29T23:16:49.297 回答