如何衡量JSF中的动作执行时间?

时间:2012-03-02 15:01:21

标签: java jsf

我正在寻找一种方法来衡量我在JSF应用程序中所有操作的执行时间。

到目前为止我发现的一个hacky解决方案是扩展 com.sun.faces.application.ActionListenerImpl ,覆盖 processAction ,并调用 super.processAction 在我的实现中:

public class MyActionListener extends ActionListenerImpl {

            public void processAction(ActionEvent event) throws FacesException {
                   watch.start();
                    super.processAction(event);
                   watch.stop();
            }
}

然后我将自己的ActionListener实现添加到faces config:

<application>
        <action-listener>MyActionListener</action-listener>
</application

但是这增加了对jsf-impl的依赖性并且是hacky。有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

您可以改用PhaseListener并挂钩PhaseId.INVOKE_APPLICATION

public class MyPhaseListener implements PhaseListener {

    public PhaseId getPhaseId() {
        return PhaseId.INVOKE_APPLICATION;
    }

    public void beforePhase(PhaseEvent event) {
        watch.start();
    }

    public void afterPhase(PhaseEvent event) {
        watch.stop();
    }

}

将其注册为<phase-listener>

注意,我知道您的代码是伪代码,但为了完整起见,我想警告您,您需要意识到所有线程/请求之间共享同一个侦听器实例。您更愿意将watch存储在请求映射中,而不是作为实例变量。

答案 1 :(得分:0)

最有效的解决方案是实现ServletContextListener,实现contextInitialized,为当前默认动作侦听器创建反射代理,并在代理的调用处理程序中测量时间。

@Override
    public void contextInitialized(ServletContextEvent sce) {
        // get JSF application factory
        ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
        Application application = applicationFactory.getApplication();
        ActionListener defaultActionListener = application.getActionListener();

        // create proxy for the default actionlistener
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        ActionListenerInvocationHandler actionListenerInvocationHandler = new ActionListenerInvocationHandler(defaultActionListener);
        @SuppressWarnings("rawtypes")
        Class[] interfaces = new Class[] { ActionListener.class };
        ActionListener actionListenerProxy = (ActionListener) Proxy.newProxyInstance(contextClassLoader, interfaces, actionListenerInvocationHandler);

        // set proxied actionListener as new default actionlistener
        application.setActionListener(actionListenerProxy);

    }