15

私のアプリケーションではBean検証がうまく機能しています。ここで、新しいユーザーがすでに選択されているユーザー名を選択していないことを確認したいと思います。

actionlistenerにはデータベースをチェックするコードがありますが、既存のユーザー名を選択した場合、ユーザーを強制的に元のページに戻すにはどうすればよいですか?

4

5 に答える 5

18

序章

あなたはそれを行うことができますが、JSF ajax / action/listenerメソッドは意味的に検証を行うのに間違った場所です。フォームへの入力値が間違っている場合、実際にはJSFライフサイクルでそれほど遠くまで行きたくありません。JSF検証フェーズの後でJSFライフサイクルを停止する必要があります。

JSR303 Bean Validationアノテーション(@NotNullおよびその仲間)や制約バリデーターを使用するか、代わりにJSF Validatorrequired="true"<f:validateXxx>など)を使用します。これは、JSF検証フェーズ中に適切に呼び出されます。このように、検証が失敗した場合、モデル値は更新されず、ビジネスアクションは呼び出されず、同じページ/ビューに留まります。

特定の入力値がデータベースに従って一意であるかどうかを確認するための標準のBeanValidationアノテーションまたはJSFValidatorがないため、そのためのカスタムバリデーターを自家栽培する必要があります。

どちらの方法でも、ユーザー名の一意性をチェックするカスタムバリデーターを作成する方法を示します。

カスタムJSR303Bean検証注釈

まず、カスタム@Username制約アノテーションを作成します。

@Constraint(validatedBy = UsernameValidator.class)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Username {
    String message() default "Username already exists";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

この制約バリデーターを使用すると(注:@EJBまたはCDI 1.1以降でのみ動作するため、CDI 1.0を使用して@InjectいるConstraintValidator場合は、JNDIから手動で取得する必要があります):

public class UsernameValidator implements ConstraintValidator<Username, String> {

    @EJB
    private UserService service;

    @Override
    public void initialize(Username constraintAnnotation) {
        // If not on CDI 1.1 yet, then you need to manually grab EJB from JNDI here.
    }

    Override
    public boolean isValid(String username, ConstraintValidatorContext context) {
        return !service.exist(username);
    }

}

最後に、モデルで次のように使用します。

@Username
private String username;

カスタムJSFバリデーター

別の方法は、カスタムJSFバリデーターを使用することです。JSFValidatorインターフェースを実装するだけです。

@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {

    @EJB
    private UserService userService;

    @Override
    public void validate(FacesContext context, UIComponent component, Object submittedAndConvertedValue) throws ValidatorException {
        String username = (String) submittedAndConvertedValue;

        if (username == null || username.isEmpty()) {
            return; // Let required="true" or @NotNull handle it.
        }

        if (userService.exist(username)) {
            throw new ValidatorException(new FacesMessage("Username already in use, choose another"));
        }
    }

}

最後に、ビューで次のように使用します。

<h:inputText id="username" ... validator="#{usernameValidator}" />
<h:message for="username" />

@FacesValidator通常はクラスでアノテーションを使用しますValidatorが、次のJSF 2.3までは、@EJBまたはをサポートしていないことに注意してください@Inject@EJB、@ PersistenceContext、@ Inject、@Autowiredを使用して@FacesValidatorに注入する方法も参照してください。

于 2011-05-05T11:50:28.857 に答える
4

はい、できます。アクションリスナーメソッドで検証を実行し、カスタム検証が失敗した場合はフェイスメッセージを追加して、FacesContext.validationFailed()戻る直前に呼び出すことができます。

このソリューションの唯一の問題は、JSF検証とBean検証の後に発生することです。つまり、検証フェーズの後です。複数のアクションリスナーがある場合、たとえば、listener1とlistener2:listener1でのカスタム検証が失敗した場合、listener2は引き続き実行されます。しかし結局のところ、AJAX応答でvalidationFailedを取得します。

于 2012-02-09T14:35:58.463 に答える
1

この目的には、actionListenerではなくactionメソッドを使用することをお勧めします。次に、ユーザー名が存在する場合は、このメソッドから戻るnull(アクションをトリガーしたページを再ロードする)ことができます。次に例を示します。

フェイスレット内:

<h:commandButton action="#{testBean.doAction}" value="and... Action"/>

Beanで:

public String doAction() {
   if (userExists) {
     return null;
   } else {
     // go on processing ...
   }
}
于 2011-05-05T06:36:18.993 に答える
0

エンドユーザーにフィードバックを提供する場合:

xhtml:

    <p:commandButton value="Go" process="@this" action="#{myBean.checkEntity()}" oncomplete="if(args.validationFailed){PF('widgetOldInfoNotice').show();}"/>

    <p:confirmDialog id="dialogOldInfoNotice" header="NOTICE" severity="alert" widgetVar="widgetOldInfoNotice">
    -- feedback message--
<p:button value="Ok" onclick="PF('widgetOldInfoNotice').hide();"/>
    </p:confirmDialog>

豆:

public String checkEntity() {
    if (!dao.whateverActionToValidateEntity(selectedEntity)) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.validationFailed();
        return "";
    }
    return "myPage.xhtml";
}
于 2019-06-20T23:52:24.717 に答える
-1

ナビゲーションケースは、faces-config.xmlファイルで定義できます。これにより、Beanの戻り値に応じて、ユーザーを特定のページにリダイレクトできます。

以下の例では、suerは「myMethod()」の戻り値に応じて2つのページのいずれかにリダイレクトされます。

 <navigation-rule>
  <from-view-id>/index.xhtml</from-view-id>
  <navigation-case>
   <from-action>#{myBean.myMethod()}</from-action>
   <from-outcome>true</from-outcome>
   <to-view-id>/correct.xhtml</to-view-id>
  </navigation-case>
  <navigation-case>
   <from-action>#{myBean.myMethod()}</from-action>
   <from-outcome>false</from-outcome>
   <to-view-id>/error.xhtml</to-view-id>
  </navigation-case>
 </navigation-rule>
于 2011-05-05T08:56:39.863 に答える