我正在处理一个大型 Grails 1.3.7 项目,我想从过滤器访问流状态名称以进行日志记录。我一直在谷歌上搜索,我能找到的最接近的答案是:Grails WebFlow State Name,但它只能在流程本身内工作。
有没有办法从流(过滤器)外部获取当前会话中正在执行的流的状态名称?
提前致谢,
吉列尔莫
我正在处理一个大型 Grails 1.3.7 项目,我想从过滤器访问流状态名称以进行日志记录。我一直在谷歌上搜索,我能找到的最接近的答案是:Grails WebFlow State Name,但它只能在流程本身内工作。
有没有办法从流(过滤器)外部获取当前会话中正在执行的流的状态名称?
提前致谢,
吉列尔莫
经过大量的谷歌搜索和调试后,我设法生成了以下代码。它适用于一个简单的应用程序。当我从假期回来时,我会将它与主应用程序集成,然后我会更新这个问题。
package org.glalejos
import org.springframework.context.ApplicationContext
import org.springframework.webflow.context.ExternalContext
import org.springframework.webflow.context.ExternalContextHolder
import org.springframework.webflow.context.servlet.ServletExternalContext
import org.springframework.webflow.execution.FlowExecution
import org.springframework.webflow.execution.FlowExecutionKey
import org.springframework.webflow.execution.repository.FlowExecutionRepository
class LoggingFilters {
def grailsApplication
String getFlowStateName(def grailsApplication, def servletContext, def request, def response) {
String stateName
if (grailsApplication && servletContext && request && request.queryString && response) {
try {
String strKey = null
String[] keys = request.queryString.split("&")
keys.each{ if (it.startsWith("execution=")) strKey = it.substring(10)}
if (strKey != null) {
ApplicationContext ctx = grailsApplication.mainContext
FlowExecutionRepository fer = ctx.getBean("flowExecutionRepository")
FlowExecutionKey fek = fer.parseFlowExecutionKey(strKey)
ExternalContext previousContext = ExternalContextHolder.getExternalContext()
try {
// You have to set an external context before invoking "fer.getFlowExecution()" or it'll throw a NPE
ExternalContextHolder.setExternalContext(new ServletExternalContext(servletContext, request, response));
FlowExecution fe = fer.getFlowExecution(fek)
stateName = fe.getActiveSession().getState().getId()
} finally {
ExternalContextHolder.setExternalContext(previousContext);
}
} else {
stateName = null
}
} catch(Exception e) {
stateName = null
}
} else {
stateName = null
}
return stateName
}
def filters = {
logData(controller:"*", action:"*") {
before = {
println("Incoming request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}")
}
after = {
println("Dispatched request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}")
}
}
}
}
编辑:上面的代码可以确定给定时间点的当前流状态的名称,但随着流执行的发展,它不会更新日志框架的映射诊断上下文。为此,有必要实现 aorg.springframework.webflow.execution.FlowExecutionListener
并将其注册在conf/spring/resources.groovy
:
beans = {
myLoggingFlowExecutionListener(org.example.MyLoggingFlowExecutionListener)
}
您必须在 bean 中注册此侦听器 bean 和hibernateConversationListener
bean executionListenerLoader
,但是,出于某种原因,Spring DSL 在这种情况下不起作用(请参阅下面的 EDIT2)。因此,resources.xml
您可以将其放置在同一文件夹中resources.groovy
,以便正确声明您的资源:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="executionListenerLoader" class="org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader">
<constructor-arg>
<list>
<ref bean="hibernateConversationListener" />
<ref bean="myLoggingFlowExecutionListener" />
</list>
</constructor-arg>
</bean>
</beans>
每个FlowExecutionListener
方法都接收到许多可用于记录目的的上下文信息(为了清楚起见,我省略了此类的实现)。
EDIT2:在流的生命周期中操作域对象时,未能将hibernateConversationListener
bean 添加到executionListenerLoader
Hibernate 异常的结果中。但是,Spring DSL 在这种特定情况下不起作用,因此我必须使用 XML 格式声明所需的 bean。请参阅http://grails.1312388.n4.nabble.com/Registering-custom-flow-execution-listener-td2279764.html。我已将上面的代码更新为最终的工作版本。