2

テキストとリンク(別のフラグメント内)を含む別のフラグメントで構成されたListViewがあります。リストビューモデルの状態に応じて、リンクが表示されます。

簡単にするために、リストビューモデルのブールフィールドに応じてリンクが表示されているとします。trueの場合は表示され、そうでない場合は非表示になります。

最初はリンクが表示され、リンクの場所をコピーし(暗号化)、モデルが変更されるのを待ち(ブール値からfalseに)、ページを更新するとリンクがなくなります。(正しい!)

以前にコピーしたURLをブラウザに戻そうとすると、このリンクのリスナーが見つからなかったことを通知するWicketRuntimeExceptionが表示されます。

より完全にするために、リンクはフラグメント内にあります。

<wicket:fragment wicket:id="reservationRatingFragment">
    <li>
        <div>
            <img src="/img/good.png" />
        </div>
        <p>
            <a wicket:id="ratingGoodLink" href="#"> <wicket:message
                    key="messaging.reservation.rating.good" />
            </a>
        </p>
    </li>
</wicket:fragment>

そして、私が目に見えないと言うとき、私はフラグメントのマークアップコンテナを.setVisible(false);として設定したことを意味します。

なぜこうなった?表示されなくなったリンクを思い出した場合、フレームワークはそれをスキップして、現在表示しているページを更新する(またはベースページにリダイレクトする)必要があると思います。

たとえば、リンクをコピーしてBasePageを変更した場合(たとえば、ホームページに移動した場合)、コピーしたURLを呼び出したときに例外が発生します。

編集:

最初のフラグメント:

WebMarkupContainer msgRatingContainer = new WebMarkupContainer("messageRatingContainer") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onConfigure() {
                setVisible(message.getType() == MessageType.RATING);
            }
        };

if (msgRatingContainer.isVisible()) {
            if (message.getType() == MessageType.RATING) {
                msgRatingContainer.add(new ReservationRatingFragment("messageRatingSection",
                        "reservationRatingFragment", this, item, message));
}

ネストされたフラグメント(ReservationRatingFragment):

public ReservationRatingFragment(String id, String markupId,MarkupContainer markupContainer, Item item, Message msg) {
        super(id, markupId, markupContainer, new Model<Message>(msg));
        /* Avoid render container */
        setRenderBodyOnly(true);

        /* Load button components */
        Link<Void> ratingGoodLink = new Link<Void>("ratingGoodLink"){
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick() {
                processRating(ReservationEvaluationResult.GOOD);
            }   
        };
        add(ratingGoodLink);

        Link<Void> ratingBadLink = new Link<Void>("ratingBadLink"){
            private static final long serialVersionUID = 1L;
            @Override
            public void onClick() {
                processRating(ReservationEvaluationResult.BAD);
            }   
        };
        add(ratingBadLink);
    }

両方のフラグメントのマークアップ:

<wicket:fragment wicket:id="messageFragment">
    Some content...
    <!-- Here goes my fragment with link -->
    <ul wicket:id="messageRatingContainer">
        <div wicket:id="messageRatingSection"></div>
    </ul>

    <wicket:fragment wicket:id="reservationRatingFragment">
        <li><div>
                <img src="/img/messaging/good.png" />
            </div>
            <p>
                <a wicket:id="ratingGoodLink" href="#"> <wicket:message
                        key="messaging.reservation.rating.good" />
                </a>
            </p></li>
        <li><div>
                <img src="/img/messaging/bad.png" />
            </div>
            <p>
                <a wicket:id="ratingBadLink" href="#"> <wicket:message
                        key="messaging.reservation.rating.bad" />
                </a>
            </p></li>
    </wicket:fragment>
</wicket:fragment>

編集済み:processRatingは、コントローラー(バックエンドでの変更を処理する)への呼び出しを実行するだけです。コントローラでリプレイアタックをチェックし(このアクションがすでに実行されている場合)、その場合、ユーザーを警告ページに導くランタイム例外をスローします(このメッセージはすでに評価されています)。実際には、この場合、リンクが利用できないため、コントローラーを呼び出さず、リンクが表示されないため、InvalidUrlExceptionがスローされるため、この時点には到達しません。

ウィケットバージョン:1.4.19

ありがとう

4

3 に答える 3

5

無効なリンクが無視されるか、ベース ページにリダイレクトされるというあなたの想定は間違っています。

何故ですか?

一歩後退すると、リンクをクリックするとどうなりますか? アプリケーションの状態が変化します。ただし、これは、アプリケーションがリンクが作成されたときの状態にある場合にのみ安全です。このルールが適用されなかった場合は、すべての潜在的な状態遷移が許容されるか、明示的に無効としてマークされていることを確認する必要があります。これは、ほとんどのシステムで不可能ではないにしても、非常に非現実的です。ただし、これを無視すると、セキュリティ上のリスクになるだけでなく、データが破損する可能性があります。

楽観的ロックの場合と考えるのが最善です。(ほとんどの場合:)) リンクが作成されると、作成時の内部状態のバージョン番号が与えられます。リンクをクリックすると、そのバージョン番号が内部状態の現在のバージョンと比較されます。2 つが一致する場合、リンクは有効として受け入れられ、内部状態が更新され、そのバージョン番号がインクリメントされます。2 つの数値が一致しない場合、無効な状態遷移の試みは無視できないため、リンクは拒否され、例外がスローされます。

この制限を回避する方法については、別の回答で既に説明されているため、説明しません。「なぜ」という質問に答えたかっただけです。

于 2012-10-29T23:38:35.233 に答える
1

私が見つけた唯一の実行可能な解決策は、RequestCycleを拡張し、次のようにonRuntimeExceptionメソッドをオーバーライドすることでした。

@Override
public Page onRuntimeException(Page page, RuntimeException e) {     
    if(e instanceof InvalidUrlException) {
        return new HomePage();
    } else {
        return super.onRuntimeException(page, e);
    }
}
于 2012-10-30T16:13:14.463 に答える
1

あなたの実装の正確な理由を理解しているかどうかはわかりません。つまり、PageParameters を設定した BookmarkablePageLink() を使用して、目的のページの読み込み時に processRating() メソッドを実行することをお勧めします。

リンク コンポーネントを追加します。

    PageParameters ppGood = new PageParameters("0="+ReservationEvaluationResult.GOOD);
    PageParameters ppBad = new PageParameters("0="+ReservationEvaluationResult.BAD);
    add(new BookmarkablePageLink("ratingGoodLink", DestinationPage.class, ppGood));
    add(new BookmarkablePageLink("ratingBadLink", DestinationPage.class, ppBad));

次に、DestinationPage に新しいコンストラクターを作成します。

public class DestinationPage extends WebPage {
    public DestinationPage(PageParameters param) {
        if(param.getString("0")!=null){
            String rating = param.getString("0");
            processRating(rating);
        }
     ...

これにより、永続的なリンクが提供され、URL をコピーして貼り付けることができます。

于 2012-10-29T23:01:55.803 に答える