如何记录JSF ajax请求的方法表达式
我已经想出了如何在过滤器中记录请求是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()); }
此信息仅在JSF组件树中可用. JSF组件树仅在视图构建时间之后可用.只有在FacesServlet提供请求时才会构建视图.因此,servlet过滤器在任何servlet之前运行时太早. 您最好在回发的还原视图阶段之后运行代码. JSF组件树保证在那一刻可用.您可以使用 获得相关的行为监听器反过来又是一个故事.这在 总而言之,这就是在侦听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开始,你可以使用新的 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. } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |