grails - 从过滤器访问流状态名称

标签 grails spring-webflow

我正在处理一个大型Grails 1.3.7项目,并且我想从过滤器访问流状态名称以进行记录。我一直在搜索很多东西,而我能找到的最接近的答案是:Grails WebFlow State Name,但是它仅在流本身内部有效。

有什么方法可以从流(过滤器)外部获取当前 session 中正在执行的流的状态名称?

提前致谢,

吉列尔莫

最佳答案

经过大量的Google搜索和调试后,我设法生成了以下代码。它可以在一个简单的应用程序中工作。假期回来时,我会将其与主应用程序集成,然后更新此问题。

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)}")
            }
        }
    }
}

编辑:上面的代码可以确定给定时间点当前流状态的名称,但是随着流执行的发展,它不会更新日志记录框架的映射诊断上下文。为此,有必要实现一个org.springframework.webflow.execution.FlowExecutionListener并将其注册在conf/spring/resources.groovy中:
beans = {
    myLoggingFlowExecutionListener(org.example.MyLoggingFlowExecutionListener)
}

您必须在hibernateConversationListener bean中注册此侦听器bean和executionListenerLoader bean,但是由于某种原因,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会导致休眠异常。但是,Spring DSL在这种特定情况下不起作用,因此我不得不使用XML格式声明所需的bean。参见http://grails.1312388.n4.nabble.com/Registering-custom-flow-execution-listener-td2279764.html。我已经将上面的代码更新为最终的工作版本。

关于grails - 从过滤器访问流状态名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15268603/

相关文章:

java - Spring Webflow : binding does not work with map although map values are in the httprequest

java - 弹出 JSF 中的 URL

validation - 在 Spring Webflow 中进行验证之前评估方法

java - grails 应用程序中的 "Too many open files"- 如何正确关闭打开的文件和流?

authentication - Grails spring security LDAP 从 LDAP 基础获取 ROLE

java - 如何从 Spring Web Flow XML 获取 session ?

grails - Grails Webflow:将一组新的参数与现有的flow变量合并

grails: "business controller"加上一个管理脚手架=true Controller

grails - Grails无法使用ID以外的ID名称更新行

json - 使用 Grails Spring Security Plugin Core 和 REST 从用户响应中省略密码字段