我正在开发基于 JSF 2 Mojarra 构建的 Web 应用程序。我需要通过我的 servlet 过滤器记录一些仪器信息。为此,我还需要知道调用了哪个 ManagedBean 和哪个方法。
有没有办法获取这些信息?我无法访问FacesContext
,因为在请求到达 Faces Servlet 之前调用了过滤器。
我正在开发基于 JSF 2 Mojarra 构建的 Web 应用程序。我需要通过我的 servlet 过滤器记录一些仪器信息。为此,我还需要知道调用了哪个 ManagedBean 和哪个方法。
有没有办法获取这些信息?我无法访问FacesContext
,因为在请求到达 Faces Servlet 之前调用了过滤器。
我收集到您想要记录UICommand
正在调用的组件。servlet 过滤器不适合这种情况,因为它无法访问FacesContext
,更不用说UIViewRoot
您最终需要遍历的了。(FacesContext
本质上也是UIViewRoot
, et.al )是由FacesServlet
作为一个体面的 servlet 创建的,它完全符合在所有过滤器之后调用的servlet 规范。因此,不可能掌握servlet 过滤器的内部。诚然,有一些方法可以创建您自己的实例,但如果存在满足要求的“正确方法”,则绝对不建议这样做。FacesContext
FacesContext
您应该为这项工作使用正确的工具,在这种特殊情况下是相位监听器。这是一个阶段监听器的外观和应该注册的启动示例:
public class MyPhaseListener implements PhaseListener {
@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
@Override
public void beforePhase(PhaseEvent event) {
// Do your job here which should run right before the RESTORE_VIEW phase.
}
@Override
public void afterPhase(PhaseEvent event) {
// Do your job here which should run right after the RESTORE_VIEW phase.
}
}
要让它运行,请在以下位置注册它faces-config.xml
:
<lifecycle>
<phase-listener>com.example.MyPhaseListener</phase-listener>
</lifecycle>
您可以将getPhaseId()
结果更改为您的洞察力,例如PhaseId.RENDER_RESPONSE
,然后阶段侦听器将在渲染响应阶段之前和之后启动。
这是一个具体的启动示例,它可以完成您正在寻找的工作(查找正在调用的命令组件并记录其操作方法表达式):
public class InvokedCommandComponentLogger implements PhaseListener {
@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
@Override
public void beforePhase(PhaseEvent event) {
// NOOP. The view hasn't been restored yet at that point, so the component tree wouldn't be available anyway.
}
@Override
public void afterPhase(PhaseEvent event) {
FacesContext context = event.getFacesContext();
if (context.isPostback()) {
UICommand component = findInvokedCommandComponent(context);
if (component != null) {
String methodExpression = component.getActionExpression().getExpressionString();
System.out.println("Method expression of the action being invoked: " + methodExpression);
}
}
}
private UICommand findInvokedCommandComponent(FacesContext context) {
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
Set<String> clientIds = new HashSet<>();
if (context.getPartialViewContext().isAjaxRequest()) {
clientIds.add(params.get("javax.faces.source")); // This covers <f:ajax> inside UICommand.
} else {
for (Entry<String, String> entry : params.entrySet()) {
if (entry.getKey().equals(entry.getValue())) { // This covers UIForm and UICommand components.
clientIds.add(entry.getKey());
}
}
}
EnumSet<VisitHint> hints = EnumSet.of(VisitHint.SKIP_UNRENDERED);
final UICommand[] found = new UICommand[1];
context.getViewRoot().visitTree(VisitContext.createVisitContext(context, clientIds, hints), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target instanceof UICommand) {
found[0] = (UICommand) target;
return VisitResult.COMPLETE;
} else {
return VisitResult.ACCEPT;
}
}
});
return found[0];
}
}