jsf 2.0在GET参数验证失败后返回http错误代码

时间:2011-05-31 10:20:42

标签: jsf facelets

我有这个本地网址: http://localhost:8084/Name/faces/Blah.xhtml?flkatid=AAA

这是一个来自facelet的片段,它检查参数“flkatid”并将其分配给bean:

    <f:metadata>
        <f:viewParam name="flkatid"
                     id="flkatid"
                     value="#{floKatBean.flkatid}"
                     required="true"
                     requiredMessage="URL incomplete"
                     validator="#{floKatBean.validateFlKatId}"
                     validatorMessage="URL incomplete or invalid"
                     >
        </f:viewParam>
        <f:event type="preRenderView" listener="#{floKatBean.init}"/>
        <f:event type="preRenderView" listener="#{floBean.holFloListe}"/>
    </f:metadata>

floKatBean.flkatid是一个整数,因此URL无效。将显示一个页面,告诉您:

flkatid:'AAA'必须是由一个或多个数字组成的数字。 flkatid:'AAA'必须是-2147483648和2147483647之间的数字示例:9346

JSF检查参数本身,因为它知道bean元素是一个整数。仅当参数是整数时才调用自定义验证器。

是否可以让服务器返回HTTP错误代码,例如403(禁止)没有离开“标准JSF世界”(或切换到RichFaces,MyFaces,SmileyFaces或其他)?我在f:viewParam中找不到任何“失败”的页面。也许在其他地方?

2 个答案:

答案 0 :(得分:3)

您可以在验证器中执行ExternalContext#responseSendError()。但是这需要将值声明为String而不是Integer并且required="true"已被删除,所有这些都是为了防止JSF默认验证机制进行空/空检查和从String转换为Integer

<f:metadata>
    <f:viewParam name="flkatid" value="#{floKatBean.flkatid}" 
        validator="#{floKatBean.validateFlKatId}" 
        validatorMessage="URL incomplete or invalid" 
    />
    ...
</f:metadata>

public void validate(FacesContext context, UIComponent component, Object value) 
    throws ValidatorException, IOException
{
    if (value == null || !((String) value).matches("\\d+")) {
        context.getExternalContext().responseSendError(
            403, (String) component.getAttributes().get("validatorMessage"));
    }
}

您可以使用init()方法进行转换。

this.flkatidInteger = Integer.valueOf(this.flatkid);

答案 1 :(得分:0)

我发现执行此操作的最佳方法(处理请求参数和发送有用的HTTP响应)是完全删除f:viewParam,并使用{{1中的参数“手动”处理像这样的监听器:

preRenderView

然后,在视图中:

public void preRenderViewCheckParameters() throws IOException {
    if (!isPostback()) {
        flkatid = getFlkatidFromRequest();
        if (flkatid == null) {
            responseSendError(404, "URL incomplete or invalid!");
        }
    }
}
private Integer getFlkatidFromRequest(){
    try {
        return Integer.valueOf(getRequestParameter("flkatid"));
    } catch (NumberFormatException e) {
        return null;
    }
}

// util methods stolen from OmniFaces (check out this project, you'll love it):
// https://github.com/omnifaces/omnifaces/blob/master/src/org/omnifaces/util/Faces.java
public static String getRequestParameter(String name) {
    return FacesContext.getCurrentInstance().getExternalContext()
                       .getRequestParameterMap().get(name);
}
public static void responseSendError(int status, String message)
                           throws IOException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    facesContext.getExternalContext().responseSendError(status, message);
    facesContext.responseComplete();
}

可能会有更多代码,但至少它更直接。

另外,这样做可以避免weird problems with messages not being displayed,所以......这就是我一直在做的事情。