@PostConstruct 方法针对同一请求调用两次

发布于 2024-12-29 18:03:06 字数 1507 浏览 1 评论 0原文

我将 JSF 2.0 与 GlassFish 3.0 结合使用。

我有以下托管 Bean:

@ManagedBean
@RequestScoped
public class OverviewController{

    private List<Event> eventList;

    @PostConstruct
    public void init(){
        System.out.println("=> OverviewController - init() - enter");

        System.out.println("=< OverviewController - init() - exit");
    }
}

overview.xhtml 文件中,我从 OverviewController 中调用不同的属性或方法。

<ui:repeat var="event" value="#{overviewController.eventList}">
    ...
</ui:repeat>

一切工作正常,但问题出在日志文件上:

INFO: Enter : RESTORE_VIEW 1
INFO: Exit : RESTORE_VIEW 1

INFO: Enter : RENDER_RESPONSE 6
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: Exit : RENDER_RESPONSE 6

如您所见, init() 方法在同一个请求中无缘无故地被调用了两次。据我所知,任何用 PostConstruct 注释的方法每个请求都会调用一次。我错了吗?

编辑: 页面上没有使用AJAX。 我用 firebug 检查了请求数。发出了树请求:

  • 1.一个用于 javax.faces.resource (GET)
  • 2.一个用于 css 文件 (GET)
  • 3.一个用于overview.xhtml (获取)

I'm using JSF 2.0 with GlassFish 3.0.

I have the following Managed Bean:

@ManagedBean
@RequestScoped
public class OverviewController{

    private List<Event> eventList;

    @PostConstruct
    public void init(){
        System.out.println("=> OverviewController - init() - enter");

        System.out.println("=< OverviewController - init() - exit");
    }
}

From the the overview.xhtml file I'm calling different attributes or methods from my OverviewController.

<ui:repeat var="event" value="#{overviewController.eventList}">
    ...
</ui:repeat>

Everything works just fine but the problem is on the Log File:

INFO: Enter : RESTORE_VIEW 1
INFO: Exit : RESTORE_VIEW 1

INFO: Enter : RENDER_RESPONSE 6
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: Exit : RENDER_RESPONSE 6

As you can see, The init() method is called twice in the same request for no reason what so ever. From what I know, any method annotated with PostConstruct is called once every request. Am I wrong?

EDIT:
No AJAX is used on the page.
I checked the number of requests with firebug. There are tree requests made:

  • 1.One for the javax.faces.resource (GET)
  • 2.One for the css file (GET)
  • 3.One for overview.xhtml (GET)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

说好的呢 2025-01-05 18:03:06

如果您有多个框架管理同一个 bean 类,则可能会发生这种情况。例如,JSF CDI,或 JSF Spring,或 CDI Spring 等。仔细检查 bean 上的配置和注释。

如果您使用 CDI 并在整个类中使用多个 @Named 注释,也可能会发生这种情况。例如,直接在类上使用 @Named 将其注册为托管 bean,而在 @Produces getter 方法上使用另一个 @Named。您需要问自己这是否真的有必要。您也可以只使用 #{bean.someObject} 而不是 #{someObject}

@Named
@RequestScoped
public class Bean {

    @PostConstruct
    public void init() {
        // ...
    }

    @Named
    @Produces
    public SomeObject getSomeObject() {
        // ...
    }

}

如果您的托管 bean 扩展了某个抽象类,而该抽象类在方法上又具有 @PostConstruct ,那么也可能会发生这种情况。您应该从中删除注释。或者,您应该将 init 方法设为抽象,并且在实现 bean 上使用@PostConstruct

public abstract class BaseBean {

    @PostConstruct
    public void postConstruct() {
        init();
    }

    public abstract void init();

}

That can happen if you have multiple frameworks managing the same bean class. E.g. JSF and CDI, or JSF and Spring, or CDI and Spring, etc. Doublecheck your configuration and annotations on the bean.

That can also happen if you're using CDI and are using multiple @Named annotations throughout the class. For example, a @Named straight on the class to register it as a managed bean and another one on a @Produces getter method. You'd need to ask yourself whether that is really necessary. You could also just use #{bean.someObject} instead of #{someObject}.

@Named
@RequestScoped
public class Bean {

    @PostConstruct
    public void init() {
        // ...
    }

    @Named
    @Produces
    public SomeObject getSomeObject() {
        // ...
    }

}

That can also happen if your managed bean extends some abstract class which has in turn also a @PostConstruct on the method. You should remove the annotation from it. Alternatively, you should make the init method abstract and not have @PostConstruct on the implementing bean:

public abstract class BaseBean {

    @PostConstruct
    public void postConstruct() {
        init();
    }

    public abstract void init();

}
2025-01-05 18:03:06

init() 方法和 @PostConstruct 方法可能都会触发并导致此行为。尝试更改 init() 方法的名称和/或将其设置为 private。我认为这可能与您的问题有关:

http: //javahowto.blogspot.com/2011/07/servlet-init-method-vs-postconstruct.html

我还在这里找到了一篇关于调试 JSF 生命周期的好文章:
调试 JSF 生命周期

It is possible that the both init() method and @PostConstruct methods are firing and causing this behavior. Try changing the name of the init() method and/or putting it private. I think that this may be related to your problems:

http://javahowto.blogspot.com/2011/07/servlet-init-method-vs-postconstruct.html

I also found a good post about debugging JSF life cycles here:
Debug JSF lifecycle

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文