0

舞台裏で Web サービスを使用するサービス API を使用する UI クライアントを構築しています。API サービスの 1 つが次のようになります。

interface UserService {
    List<User> findUsers(User loggedInUser, UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
    void removeUser(User loggedInUser, User userToRemove) throws AutheticationFault;
    void addUser(User loggedInUser, User newUser) throws AuthenticationFault;
}

LoggedInUser は、代わりにメソッドが呼び出されるユーザーです。AuthenticationFault はチェック例外です。これらのサービス インターフェイスは 20 ほどあります。私がやりたいことは、loggedInUser パラメーターと AuthenticationFault 例外を隠すファサードを実装することです。ファサードの実装は、現在クライアントにログインしているユーザーでこれらのメソッドを呼び出します。

また、他のチェック済み例外についてもクリーニングを行いたいと思います。ご覧のとおり、クライアントがページ -1 を取得しようとしたときにスローされる InvalidIndexFault 例外がありますが、これはプログラマーのエラーであり、チェック例外として使用したくありません。

現在、私がやったことは、好きではない例外に対して常に RuntimeException を再スローすることですが、後で気が変わった場合、後でそれを変更するのは大変な作業です。これもコードの重複のように感じます。他のプログラマーは例外を飲み込んでログに記録するだけで、まったく恐ろしいことです。ほとんどの場合、例外が発生した場合は、エラーを表示する UI のエラー ハンドラーにバブルアップしたいと考えています。

私の頭に浮かんだいくつかの解決策がありました:

  1. Java 動的プロキシ
  2. コード生成

私はこれらの解決策を試してみることができなかったので、最初にここで質問したほうがよいと考えました. これをどのように実装することをお勧めしますか? 環境はJava 6で、ビルドツールはMaven 3です。

PS。これに答える場合は、「番号 2 を選択」以上のことを言ってください :) ヒントやその他の実装の詳細を歓迎します。

明確化として、現在ログインしているユーザーを取得することは問題ではないため、私を手伝う必要はありません。私は現在、それをインターフェースの背後に隠し、IoC を使用して注入しています。舞台裏で ThreadLocals を使用

4

1 に答える 1

1

これは完璧なユースケースになると思います

  1. Java 動的プロキシ
  2. スレッド ローカル

解明するには:

まず、Facade Interface を作成します。

インターフェイス UserServiceFacede {
    リストfindUsers(UserSearchParameters searchParameters、PagingParameters pagingParameters)はAuthenticationFault、InvalidIndexFaultをスローします。
    void removeUser(User userToRemove) は、AutheticationFault をスローします。
    void addUser(User newUser) は AuthenticationFault をスローします。
}

次に、 InvocationHandler を実装します。

public class UserHandler は InvocationHandler を実装します{
    プライベート最終 UserService サービス。

    public UserHandler(UserService サービス) {
       this.service = サービス;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       ....
       // メソッドの引数に基づいて、実際のサービスで適切な関数を呼び出します
       // 物体
       ....
    }
}

次に、次のように Proxy オブジェクトを作成します。

  UserServiceFacade uProxy = (UserServiceFacade)Proxy.newProxyInstance(UserHandler.class.getClassLoader(),
                                        new Class[] { UserServiceFacade.class},
                                        新しい UserHandler(userService));

最初の引数はクラスローダ、2 番目はプロキシが確認する必要があるインターフェイスのリスト、3 番目はハンドラ オブジェクトです。

問題は、loggedinUser のハンドルをどのように取得するかです。ここでThreadLocalの出番です。

ログインしたユーザーを保持する ThreadLocal 静的変数を作成します。次に、現在のユーザーを ThreadLocal に設定してから、プロキシを呼び出します

     private static final ThreadLocal loggedinUser = ...;
     ...
     ...
     loginUser.set(現在のユーザー);
     // 上記のようにユーザー Proxy オブジェクトを作成します..
     uProxy.findUser(searchParams, ..);
     ...

ハンドラーの呼び出し関数内の ThreadLocal からユーザーを取得します。これで、ハンドラー内で、loggedinUser (を使用loggedinUser.get()) とユーザー サービス オブジェクト (サービス オブジェクトをハンドラーのコンストラクターに渡しました)の両方にアクセスできます。

例外の処理方法に関する限り、私が行うことは通常、RuntimeExceptions のサブクラスをスローし続けることです。次に、アプリの周辺レイヤーでこれらをキャッチします。周辺層とは、アプリ/ライブラリへのエントリ ポイントを意味します。webbApp を開発している場合、これがサーブレットになります。

于 2011-07-31T14:53:18.160 に答える