3

中規模のJavaWebアプリケーションの例外について質問があります。JDBCを使用して実装されたデータアクセス層があり、ロジックは主にサーブレットに集中しています(UIはJSPです)。このようなアプリケーションの従来の例外の階層は何ですか?

データアクセス層で例外をキャッチし、全体に対して別の例外を再スローするか(DataAccessExceptionなど)、または単に最高レベルでそれらを処理する必要があります(servlet)。

さらに、データアクセス層内で呼び出される接続プールがあり、独自のタイプの例外があります。これらの例外はデータアクセス層内でキャッチされ、DataAccessExceptionとして再スローされる必要がありますか、それとも上位レベルで直接処理される必要がありますか?

LogicExceptionとTechnicalExceptionの2つの子を持つメインアプリケーション例外を設定することをお勧めします。ロジックにはAuthentificationFailedExceptionなどと同様のサブクラスがありますが、TechnicalExceptionsは、データアクセス層の例外やFileNotFound(必要な場合)などの障害に関する情報を伝達する責任がありますか?

ありがとうございました!

4

4 に答える 4

2

アプリケーションでは、すべての例外がそれらをスローしたレイヤーでキャッチされ、より一般的な例外(この場合はDataAccessException)にラップされてから、その方法で再スローされました。これは、通常、例外が発生するレイヤーにはコンテキストに関する十分な情報がないため、エラーを適切に処理する方法を決定できないためです。これらの例外を処理するのに最適な場所は、例外がスローされたレイヤーのすぐ上にあるレイヤーです。このレイヤーには、例外がスタックstraceで行き過ぎないようにすることなく、「正常に失敗」するのに十分な情報があります。あなたの場合、サーブレットで例外をキャッチすることで作業を行うことができます。

ただし、例外の階層は、作業しているアプリケーションによって異なります。あなたの論理技術部門は良い選択かもしれません...またはそうでないかもしれません。:)「例外処理」には「正しい」選択はなく、単一のQ&Aペアで処理するには複雑すぎる議論です。:)

于 2012-05-14T20:05:30.863 に答える
2

通常、私は低レベルの例外を高レベルのより意味のある例外でラップします。これは通常、より多くの作業ですが、レイヤー間のデカップリングを提供します。

たまたまデータベースから読み取る構成サブシステムを作成していると想像してください。ラップしないと、次のようになります。

public String getConfigurationProperty(String name) throws SQLException {
    // Try to read from my configuration table
}

ラッピングをすれば

public String getConfigurationProperty(String name) throws ConfigurationException {
    try {
        // Try to read from my configuration table 
    } catch (SQLException ex) {
        ConfigurationException wrapper = // Some subclass of ConfigurationException that wraps ex
        throw wrapper;
    }
}

これは間違いなくより多くの作業です。利点は、後で構成バックエンドを、ラッパーなしでファイルベースのバックエンドに変更したい場合、メソッドが次のようになることです。

public String getConfigurationProperty(String name) throws IOException {
    // Try to read from my configuration file
}

そして、sではなくsを処理するように、すべてのクライアントコードを変更する必要があります。ラッピングを行う場合は、バックエンドを変更するだけで済みます。これは、クライアントコードがすでにsとそのサブクラスを念頭に置いて記述されているためです。これは、チェックされた例外とチェックされていない例外のどちらを使用するかとは無関係であることに注意してください。例外処理を行う場合は、ほとんどの場合、処理する例外のタイプの少なくともある程度の概算を知る必要があります。IOExceptionSQLExceptionConfigurationException

さて、これは私がしがちなことです。ほとんどの例外はとにかく適切に処理できないと考える人がいて、これらすべてのラッピングはほとんどの場合ナンセンスです。

public String getConfigurationProperty(String name) throws ConfigurationException {
    try {
        // Try to read from my configuration file 
    } catch (IOException ex) {
        ConfigurationException wrapper = // Some subclass of ConfigurationException that wraps ex
        throw wrapper;
    }
}
于 2012-05-14T20:28:52.090 に答える
2

一般に、アプリケーションの特定のレイヤーでは、キャッチされた例外がそのレイヤーにとって意味のあるものになるようにする必要があります。したがって、サーブレット(またはMVCコントローラー)でSybaseExceptionをキャッチしたくない場合は、おそらくそのレベルの実装の詳細を非表示にするDAOレイヤーがあるためです。

カップルの一般的なヒント:

  • 500エラーで適切なページを返すようにapache+servletコンテナを設定する必要があります。
  • コントローラは、ほとんどのエラーをユーザーフレンドリーなメッセージでラップする必要があります。キャッチされた例外は、コントローラーが適切なメッセージを作成するための十分な情報を提供する必要があります。
  • 技術的なエラーメッセージとローカライズされたユーザーエラーメッセージの両方を含むベースアプリケーション例外を使用してRuntimeExceptionをサブクラス化することを検討します。
  • あなたがそれを捕まえたとき、あなたが例外を除いてをしたいのかを考えてください。必要なことを簡単に実行できるように、例外を設計します。

最後に、すべての人がこれに同意するわけではありませんが、すべての例外をRuntimeExceptionのサブクラスにして、チェックを外すという強力な主張をすることができます。私はこのアプローチを採用する多くの大規模なコードベースに取り組んできましたが、通常は正常に機能し、多くのキャッチリスローボイラープレートコードを削減します。javaがチェックされた例外を提供するからといって、それらを使用する必要があるという意味ではありません。これは明らかに私の意見ですが、すべての人がチェックされた例外を使用するわけではなく、実際、多くのコードベースが明示的にそれらを回避することを理解することが重要です。

于 2012-05-14T20:34:50.067 に答える
1

また、中規模のWebアプリケーションの開発にも携わっています。私たちが使用した方法は、データベース層から、例外をキャッチしてユーザーに正しいエラーメッセージを生成するロジックを処理するサーブレットまで例外をスローする方法です。

これは.... IMOに行く方法ではありません。理由:サーブレット全体が実装に依存するようになりました。実装を切り替えたいとしましょう(現時点では切り替えたい)。新しい実装では同じ例外がスローされないため、残りのサーブのすべてのキャッチを変更する必要があります。一般的な例外は正しい選択です。

例外だけでなく、ビジネスオブジェクトも一般的である必要があります。できればインターフェース。これにより、実装をより簡単に変更できるようになりますが、locig処理コードは、サーブレット全体を通じて同じオブジェクトに依存します。

于 2012-05-14T20:09:44.730 に答える