当托管bean构造函数发送404 ERROR CODE时,JSF调用方法

时间:2014-09-03 04:54:30

标签: jsf jsf-2

在JSF托管bean构造函数中,我从数据库usint加载一个实体请求参数。有时,实体不在数据库中,我想显示其他带有404消息的JSF(.xhtml)页面。
这是托管bean的示例:

@ManagedBean(name = "someBean")
@RequestScoped
public class SomeBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private SomeData someData;

    public SomeBean() throws IOException {
        someData = ... loads from database using JPA features
        if(someData == null){
              HttpServletResponse response = (HttpServletResponse) FacesContext
                    .getCurrentInstance().getExternalContext().getResponse();
              response.sendError(404);
        }
    }

    public SomeData getSomeData(){
        return someData;
    }
}

我将web.xml文件配置为:

<error-page>
   <error-code>404</error-code>
   <location>/404.xhtml</location>
</error-page>

我有一个JSF页面来处理托管bean加载的实体。当实体存在时,我将在页面中使用它。像那样:

<h1>#{someBean.someEntity.name}</h1>
<h2>#{someBean.someEntity.description}</h2>
<ui:repeat value="#{someBean.someEntity.books}" var="book">
// ..........
</ui:repeat>

当托管成功加载数据时,上面的页面有效。

问题

当实体不存在且我发送404 ERROR CODE时,JSF仍处理第一页表达语言中定义的方法。
此行为使托管bean抛出NullPointerException和HTTP 500 ERRO CODE 我的404错误页面未被调用。我不知道为什么。

即使在数据库中找到实体并且404错误页面正常工作,我也会尝试发送404错误。

Enyone可以解释这个JSF行为给这个幸福吗?或提供某种显示404错误页面而不更改URL?

1 个答案:

答案 0 :(得分:4)

您基本上是在渲染视图时尝试执行前端控制器逻辑。您应该在呈现视图之前执行此操作。因为,一旦开始渲染视图,将视图更改为其他目的地已经太晚了,例如您的情况下的错误页面。您无法从客户端收回已发送的响应。

在JSF 2.2中,您可以使用<f:viewAction>

<f:metadata>
    <f:viewAction action="#{bean.init}" />
</f:metadata>
public void init() {
    // ...

    if (someCondition) {
        context.getExternalContext().responseSendError(404, "some message");
        context.responseComplete();
    }
}

(请注意,无论何时需要将javax.servlet.*类导入JSF辅助bean,都应该绝对停下来查看ExternalContext中是否已有功能,或者另外三思而后行如果你正在以正确的方式做事,例如,你可能需要一个servlet过滤器;还要注意你需要明确地告诉JSF你已经完成了响应,否则它仍然会尝试渲染视图) < / p>

在JSF 2.0 / 2.1中,您可以使用<f:event type="preRenderView">。另见其他What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?

如果您实际上尝试验证HTTP请求参数并且您也碰巧使用OmniFaces,您可以考虑将<f:viewParam>与真正的JSF验证程序一起使用,并使用OmniFaces控制sendError {{ 3}}