我已经想出了如何在过滤器中记录请求是ajax请求以及它来自哪个页面.

我真正想做的是记录ajax请求的实际内容.例如ajax调用的方法的名称(例如,此调用中的“findAddress”:< p:ajax process =“contactDetails”update =“@ form”listener =“#{aboutYouController.findAddress}”... .) 我怎样才能做到这一点?我的应用程序有很多ajax请求,我想记录哪些是被触发的.

public class TrackingFilter implements Filter {

private static Logger LOG = Logger.getLogger(TrackingFilter.class);

@Override
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws servletexception,IOException {    

    HttpServletRequest req = (HttpServletRequest) request;

    String pageHit = req.getRequestURI().substring(req.getcontextpath().length()+1).replace(".xhtml","");
    if(!pageHit.contains("javax.faces.resource")){ // if is a url we want to log
        if ("partial/ajax".equals(req.getHeader("Faces-Request"))) {
            LOG.trace("ajax on URI: " + req.getRequestURI());
        }

What I would really like to do is log what the ajax request is actually for. Such as the name of the method being called by the ajax (eg “findAddress” in this call:<p:ajax process="contactDetails" update="@form" listener="#{aboutYouController.findAddress}" ....)

此信息仅在JSF组件树中可用. JSF组件树仅在视图构建时间之后可用.只有在FacesServlet提供请求时才会构建视图.因此,servlet过滤器在任何servlet之前运行时太早.

您最好在回发的还原视图阶段之后运行代码. JSF组件树保证在那一刻可用.您可以使用FacesContext#isPostback()检查当前请求是否为回发.您可以使用PartialViewContext#isAjaxRequest()检查当前请求是否是ajax请求.您可以使用预定义的javax.faces.source请求参数来获取ajax请求的源组件的客户端ID.您可以使用预定义的javax.faces.behavior.event请求参数来获取ajax事件名称(例如,更改,单击,操作等).

获得相关的行为监听器反过来又是一个故事.这在ActionSource2组件上很容易(例如< h | p:commandButton action =“#{...}”>),因为MethodExpressionActionSource2#getActionExpression()刚刚可用.但是,这在BehaviorBase标签处理器上并不容易(例如< ; f | p:ajax listener =“#{...}”>)因为此API没有任何方法,如getBehaviorListeners().只有方法可以添加和删除它们,但不能获取它们的列表.因此,使用名称为JSF实现特定的侦听器访问私有字段时,需要一些讨厌的反射技巧.在Mojarra它是listeners而在MyFaces它是_behaviorListeners.幸运的是,两者都可以从List中分配,它是该类型中唯一的字段,所以我们可以检查一下.一旦掌握了BehaviorListener实例的手,那么你仍然需要做另一个反射技巧来获得该实例的MethodExpression字段.呸.

总而言之,这就是在侦听RESTORE_VIEW的afterPhase的PhaseListener风格中的诡计:

public class AjaxActionLoggerPhaseListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // NOOP.
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext context = event.getFacesContext();

        if (!(context.isPostback() && context.getPartialViewContext().isAjaxRequest())) {
            return; // Not an ajax postback.
        }

        Map<String,String> params = context.getExternalContext().getRequestParameterMap();
        String sourceClientId = params.get("javax.faces.source");
        String behaviorEvent = params.get("javax.faces.behavior.event");

        UIComponent source = context.getViewRoot().findComponent(sourceClientId);
        List<String> methodExpressions = new ArrayList<>();

        if (source instanceof ClientBehaviorHolder && behaviorEvent != null) {
            for (ClientBehavior behavior : ((ClientBehaviorHolder) source).getClientBehaviors().get(behaviorEvent)) {
                List<BehaviorListener> listeners = getField(BehaviorBase.class,List.class,behavior);

                if (listeners != null) {
                    for (BehaviorListener listener : listeners) {
                        MethodExpression methodExpression = getField(listener.getClass(),MethodExpression.class,listener);

                        if (methodExpression != null) {
                            methodExpressions.add(methodExpression.getExpressionString());
                        }
                    }
                }
            }
        }

        if (source instanceof ActionSource2) {
            MethodExpression methodExpression = ((ActionSource2) source).getActionExpression();

            if (methodExpression != null) {
                methodExpressions.add(methodExpression.getExpressionString());
            }
        }

        System.out.println(methodExpressions); // Do your thing with it.
    }

    private static <C,F> F getField(Class<? extends C> classtype,Class<F> fieldType,C instance) {
        try {
            for (Field field : classtype.getDeclaredFields()) {
                if (field.getType().isAssignableFrom(fieldType)) {
                    field.setAccessible(true);
                    return (F) field.get(instance);
                }
            }
        } catch (Exception e) {
            // Handle?
        }

        return null;
    }

}

要使其运行,请在faces-config.xml中注册如下:

<lifecycle>
    <phase-listener>com.example.AjaxActionLoggerPhaseListener</phase-listener>
</lifecycle>

以上测试与Mojarra和PrimeFaces兼容,理论上也与MyFaces兼容.

更新:如果你正在使用JSF实用程序库OmniFaces,或者从版本2.4开始,你可以使用新的Components#getCurrentActionSource()实用程序方法查找当前的操作源组件,并使用Components#getActionExpressionsAndListeners()获取所有注册的操作方法和监听器的列表在给定的组件上.这也适用于常规(非ajax)请求.有了这个,上面的PhaseListener示例可以减少如下:

public class FacesActionLoggerPhaseListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.PROCESS_VALIDATIONS;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // NOOP.
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        if (!event.getFacesContext().isPostback())) {
            return;
        }

        UIComponent source = Components.getCurrentActionSource();
        List<String> methodExpressions = Components.getActionExpressionsAndListeners(source);
        System.out.println(methodExpressions); // Do your thing with it.
    }

}

如何记录JSF ajax请求的方法表达式的更多相关文章

  1. 应用程序关闭时的iOS任务

    我正在构建一个应用程序,通过ajax将文件上传到服务器.问题是用户很可能有时不会有互联网连接,并且客户希望在用户重新连接时安排ajax调用.这可能是用户在离线时安排文件上传并关闭应用程序.应用程序关闭时可以进行ajax调用吗?

  2. android – Phonegap本地构建 – jquery ajax错误:readystate 0 responsetext status 0 statustext error

    解决方法您是否在索引文件中包含了内容安全元标记?

  3. Ajax简单的异步交互及Ajax原生编写

    一提到异步交互大家就会说ajax,仿佛ajax这个技术已经成为了异步交互的代名词.那下面将研究ajax的核心对象

  4. Ajax跨域问题的解决办法汇总(推荐)

    本文给大家分享多种方法解决Ajax跨域问题,非常不错具有参考借鉴价值,感兴趣的朋友一起学习吧

  5. ajax编写简单的登录页面

    这篇文章主要为大家详细介绍了ajax编写简单登录页面的具体代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  6. ajax从JSP传递对象数组到后台的方法

    今天小编就为大家分享一篇ajax从JSP传递对象数组到后台的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  7. 解决ajax返回验证的时候总是弹出error错误的方法

    这篇文章主要介绍了解决ajax返回验证的时候总是弹出error错误的方法,感兴趣的小伙伴们可以参考一下

  8. 使用AJAX完成用户名是否存在异步校验

    这篇文章主要介绍了使用AJAX完成用户名是否存在异步校验的相关资料,需要的朋友可以参考下

  9. ajax实现无刷新省市县三级联动

    这篇文章主要为大家详细介绍了ajax实现无刷新省市县三级联动的相关资料,利用三层架构实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. jQuery Ajax 实现分页 kkpager插件实例代码

    本文通过实例代码给大家讲解了jQuery Ajax 实现分页 kkpager插件功能,需要的的朋友参考下吧

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部