문제

다음은 간단한 사용 사례입니다. <f:viewAction>.

<f:metadata>
    <f:viewParam name="id" value="#{testManagedBean.id}" maxlength="20"/>
    <f:viewAction action="#{testManagedBean.viewAction}"/>
</f:metadata>

관련된 관리되는 Bean입니다.

@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id; //Getter and setter.

    public void viewAction() {
        System.out.println("viewAction() called : " + id);
    }
}

매개변수 id URL을 통해 전달됩니다.다음과 같이 숫자가 아닌 값을 입력하면 변환 오류가 발생합니다. xxx 문제의 URL을 통해 전달되며 viewAction() 리스너와 관련된 메소드 <f:viewAction> 호출되지 않습니다.

의 가치 id ~이다 null 이 경우.다른 페이지로 리디렉션하고 싶은 경우 id 이 경우와 같이 원하는 대상 유형으로 변환할 수 없습니다. id 에서 발생할 수 있는 잠재적인 예외를 피하기 위해 지정된 유효성 검사 기준에 대해 유효성이 검사되지 않습니다. LazyDataModel#load() 해당 관리 Bean에서 이러한 매개변수에 대한 액세스가 시도될 때마다 PrimeFaces의 메소드 또는 연관된 관리 Bean의 다른 위치에 있습니다.그러기 위해서는, viewAction() 메소드를 호출해야 합니다.

어떻게 진행하나요?사용해야 할까요?

<f:event type="preRenderView">

와 함께 <f:viewAction>?

도움이 되었습니까?

해결책

이것은 지정된 행동.언제 PROCESS_VALIDATIONS 단계는 다음으로 끝납니다. 검증 실패, 둘 다 UPDATE_MODEL_VALUES 그리고 INVOKE_APPLICATION 단계를 건너뜁니다."일반" 형식과 정확히 동일합니다. <h:form>.에 대해 생각하다 <f:viewParam> 로서 <h:inputText> 그리고 <f:viewAction> 로서 <h:commandButton> 그리고 그것은 더 명확해질 것입니다.

변환/검증이 실패했을 때 리디렉션을 수행하는 특정 요구 사항에 대해 최소한 3가지 솔루션이 있습니다.

  1. 알아낸 대로 다음을 추가하세요. <f:event listener>.차라리 엮이는 게 낫겠어 postValidate 더 나은 자체 문서화를 위해 대신 이벤트를 사용하세요.

    <f:metadata>
        <f:viewParam name="id" value="#{bean.id}" maxlength="20" />
        <f:event type="postValidate" listener="#{bean.redirectIfNecessary}" />
        <f:viewAction action="#{bean.viewAction}" />
    </f:metadata>
    
    public void redirectIfNecessary() throws IOException {
        FacesContext context = FacesContext.getCurrentInstance();
    
        if (!context.isPostback() && context.isValidationFailed()) {
            context.getExternalContext().redirect("some.xhtml");
        }
    }
    

    확인 사항 FacesContext#isPostback() 동일한 보기(있는 경우)에서 "일반" 양식의 유효성 검사 실패 시 리디렉션이 수행되는 것을 방지합니다.


  2. 내장 확장 LongConverter 리디렉션을 수행하는 방법 getAsObject() (검증기는 기본 변환기로 적합하지 않습니다. Long 숫자가 아닌 입력에서는 이미 실패합니다.변환기가 실패하면 유효성 검사기가 실행되지 않습니다.)그러나 이는 설계가 좋지 않습니다(단단한 결합).

    <f:metadata>
        <f:viewParam name="id" value="#{bean.id}" converter="idConverter" />
        <f:viewAction action="#{bean.viewAction}" />
    </f:metadata>
    
    @FacesConverter("idConverter")
    public class IdConverter extends LongConverter {
    
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            if (value == null || !value.matches("[0-9]{1,20}")) {
                try {
                    context.getExternalContext().redirect("some.xhtml");
                    return null;
                }
                catch (IOException e) {
                    throw new FacesException(e);
                }
            }
            else {
                return super.getAsObject(context, component, value);
            }
        }
    
    }
    

    필요한 경우 놀 수 있습니다. <f:attribute> 내부에 <f:viewParam> 매개변수를 변환기에 "전달"합니다.

    <f:viewParam name="id" value="#{bean.id}" converter="idConverter">
        <f:attribute name="redirect" value="some.xhtml" />
    </f:viewParam>
    
    String redirect = (String) component.getAttributes().get("redirect");
    context.getExternalContext().redirect(redirect);
    

  3. 기본적으로 다음과 동일한 사용자 정의 태그 핸들러를 만듭니다. <f:event listener> 그러나 추가적인 Backing Bean 방법은 필요하지 않습니다.

    <html ... xmlns:my="http://example.com/ui">
    
    <f:metadata>
        <f:viewParam name="id" value="#{bean.id}" maxlength="20" />
        <my:viewParamValidationFailed redirect="some.xhtml" />
        <f:viewAction action="#{bean.viewAction}" />
    </f:metadata>
    

    com.example.taghandler.ViewParamValidationFailed

    public class ViewParamValidationFailed extends TagHandler implements ComponentSystemEventListener {
    
        private String redirect;
    
        public ViewParamValidationFailed(TagConfig config) {
            super(config);
            redirect = getRequiredAttribute("redirect").getValue();
        }
    
        @Override
        public void apply(FaceletContext context, UIComponent parent) throws IOException {
            if (parent instanceof UIViewRoot && !context.getFacesContext().isPostback()) {
                ((UIViewRoot) parent).subscribeToEvent(PostValidateEvent.class, this);
            }
        }
    
        @Override
        public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
            FacesContext context = FacesContext.getCurrentInstance();
    
            if (context.isValidationFailed()) {
                try {
                    context.getExternalContext().redirect(redirect);
                }
                catch (IOException e) {
                    throw new AbortProcessingException(e);
                }
            }
        }
    
    }
    

    /WEB-INF/my.taglib.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <facelet-taglib
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
        version="2.0"
    >
        <namespace>http://example.com/ui</namespace>
    
        <tag>
            <tag-name>viewParamValidationFailed</tag-name>
            <handler-class>com.example.taghandler.ViewParamValidationFailed</handler-class>
        </tag>  
    </facelet-taglib>
    

    /WEB-INF/web.xml

    <context-param>
        <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
        <param-value>/WEB-INF/my.taglib.xml</param-value>
    </context-param>
    

    사실, 약간의 코드이지만 깨끗하고 재사용이 가능합니다. <my:viewParamValidationFailed> 태그는 실제로 새로운 태그에 적합합니다. 옴니페이스 특징.

다른 팁

단순히 검증하지 않는 이유 id 당신 자신?

@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable
{
    private String id;     //Getter and setter.
    private Long validId;  //Getter and setter.

    public void viewAction() {
        try {
            validId = Long.parseLong(id);
        } catch (NumberFormatException ex) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            String outcome = "redirect.xhtml";
            facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, outcome);
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top