在 grails 3 应用程序中使用 spring webflow
Using spring webflow in grails 3 application
我一直在尝试将我的一些 grails 2 代码移植到 grails 3。此特定代码使用 grails-webflow 插件(仅在 grails 2.x 之前受支持;它现在已损坏,因为一些大修在 grails 核心中)。
所以我决定直接在我的应用程序中使用 spring webflow。我已经能够做基本的管道。那就是我有设置
* webflow 的应用上下文
* 创建流工厂和所有
* 写了流程 xml。
* 创建了其他必要的 bean。
现在,当我点击映射到我的流程的 url 时,我可以看到我的 .gsp 页面正在呈现。但问题是,它没有解决布局。页面即将到来,但没有任何 styling/layout。我缺少什么?
这是我的gsp page
。
<html>
<head>
<title><g:brandedTitle/> - Repository Database: Administrator</title>
<meta content="main" name="layout"/>
<script type="text/javascript" src="${assetPath(src: 'da.js')}"></script>
....
....
这就是我为 webflow 做管道的方式。
@Configuration
@ComponentScan
class InstallRepositoryWebflow extends AbstractFlowConfiguration {
@Autowired
GroovyPagesTemplateEngine groovyPagesTemplateEngine;
@Autowired
GroovyPageLocator groovyPageLocator;
@Autowired
GrailsLayoutViewResolver grailsLayoutViewResolver;
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
// type on browser localhost:<port>/<context-path>/hitMeToInvokeThisFlow to invoke this flow.
.addFlowLocation("/WEB-INF/flows/install-repository.xml", "installrep/install")
.build();
}
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(viewFactoryCreator())
.build();
}
@Bean
public ViewFactoryCreator viewFactoryCreator() {
List<ViewResolver> resolvers = new ArrayList<>(1);
resolvers.add(gspViewResolver());
resolvers.add(grailsLayoutViewResolver);
ViewFactoryCreator creator = new MvcViewFactoryCreator();
creator.setViewResolvers(resolvers);
return creator;
}
@Bean
ViewResolver gspViewResolver() {
GroovyPageViewResolver innerGspViewResolver = new GroovyPageViewResolver(groovyPagesTemplateEngine, groovyPageLocator);
//innerGspViewResolver.setAllowGrailsViewCaching(!gspReloadingEnabled || viewCacheTimeout != 0);
//innerGspViewResolver.setCacheTimeout(gspReloadingEnabled ? viewCacheTimeout : -1);
return innerGspViewResolver;
}
}
这是resource.groovy
中的相关部分
flowHandlerAdapter(FlowHandlerAdapter) {
flowExecutor = ref("flowExecutor");
}
flowHandlerMapping(FlowHandlerMapping) {
flowRegistry = ref("flowRegistry");
}
问题是 为什么我的布局没有被渲染?我错过了什么?
终于找到了这个问题的答案。如果我使用 SitemeshLayoutViewResolver layoutViewResolver
,而不是创建自定义解析器 GroovyPageViewResolver innerGspViewResolver = new GroovyPageViewResolver(groovyPagesTemplateEngine, groovyPageLocator);
,那么我的问题就解决了。所以基本上它必须是这样的。
@Bean
ViewResolver gspViewResolver() {
return jspViewResolver;
}
@Autowired
GrailsViewResolver jspViewResolver
这是示例项目 here,以防有人正在寻找工作示例。
更新
当我完成所有这些后,我遇到了一个非常奇怪的问题。当我 运行 来自 intellij 的应用程序时,应用程序的 webflow 部分工作正常。但是当我使用 gradlew assemble
任务创建 war
时,我总是在应用程序上看到 /error 页面。在日志中,它显示 No mapping found for HTTP request with URI * in DispatcherServlet with name 'grailsDispatcherServlet'
.
显然,我要创建的 bean 不存在。为了解决这个问题,我放弃了基于注释的配置,并将 resources.xml 文件放在 grails-app/conf/spring/
目录中。这解决了 war 的问题。这是我的配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.4.xsd">
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/flows/install-repository.xml" id="installrep/install"/>
</webflow:flow-registry>
<webflow:flow-executor id="flowExecutor" />
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="resolvers"/>
</bean>
<bean id="resolvers" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="jspViewResolver" />
</list>
</constructor-arg>
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
<property name="order" value="0"/>
</bean>
</beans>
要使用 resources.groovy 而不是 applicationContext.xml,您可以执行以下操作:
xmlns([webflow:"http://www.springframework.org/schema/webflow-config"])
webflow.flow-registry(
id:"flowRegistry",
flow-builder-services:"flowBuilderServices"
){
webflow.flow-location(
path:"/WEB-INF/flows/install-repository.xml",
id:"installrep/install"
)
}//eo flow-registry
webflow.flow-executor(id:"flowExecutor")
webflow.flow-builder-services(
id:"flowBuilderServices",
view-factory-creator:"mvcViewFactoryCreator")
mvcViewFactoryCreator(org.springframework.webflow.mvc.builder.MvcViewFactoryCreator){
viewResolvers = ref("resolvers")
}
resolvers(ArrayList, [ ref("jspViewResolver") ])
myFlowHandlerAdapter(org.springframework.webflow.mvc.servlet.FlowHandlerAdapter){
flowExecutor = ref("flowExecutor")
}
myFlowHandlerMapping(org.springframework.webflow.mvc.servlet.FlowHandlerMapping){
flowRegistry = ref("flowRegistry")
order = 0
}
我一直在尝试将我的一些 grails 2 代码移植到 grails 3。此特定代码使用 grails-webflow 插件(仅在 grails 2.x 之前受支持;它现在已损坏,因为一些大修在 grails 核心中)。
所以我决定直接在我的应用程序中使用 spring webflow。我已经能够做基本的管道。那就是我有设置 * webflow 的应用上下文 * 创建流工厂和所有 * 写了流程 xml。 * 创建了其他必要的 bean。
现在,当我点击映射到我的流程的 url 时,我可以看到我的 .gsp 页面正在呈现。但问题是,它没有解决布局。页面即将到来,但没有任何 styling/layout。我缺少什么?
这是我的gsp page
。
<html>
<head>
<title><g:brandedTitle/> - Repository Database: Administrator</title>
<meta content="main" name="layout"/>
<script type="text/javascript" src="${assetPath(src: 'da.js')}"></script>
....
....
这就是我为 webflow 做管道的方式。
@Configuration
@ComponentScan
class InstallRepositoryWebflow extends AbstractFlowConfiguration {
@Autowired
GroovyPagesTemplateEngine groovyPagesTemplateEngine;
@Autowired
GroovyPageLocator groovyPageLocator;
@Autowired
GrailsLayoutViewResolver grailsLayoutViewResolver;
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
// type on browser localhost:<port>/<context-path>/hitMeToInvokeThisFlow to invoke this flow.
.addFlowLocation("/WEB-INF/flows/install-repository.xml", "installrep/install")
.build();
}
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(viewFactoryCreator())
.build();
}
@Bean
public ViewFactoryCreator viewFactoryCreator() {
List<ViewResolver> resolvers = new ArrayList<>(1);
resolvers.add(gspViewResolver());
resolvers.add(grailsLayoutViewResolver);
ViewFactoryCreator creator = new MvcViewFactoryCreator();
creator.setViewResolvers(resolvers);
return creator;
}
@Bean
ViewResolver gspViewResolver() {
GroovyPageViewResolver innerGspViewResolver = new GroovyPageViewResolver(groovyPagesTemplateEngine, groovyPageLocator);
//innerGspViewResolver.setAllowGrailsViewCaching(!gspReloadingEnabled || viewCacheTimeout != 0);
//innerGspViewResolver.setCacheTimeout(gspReloadingEnabled ? viewCacheTimeout : -1);
return innerGspViewResolver;
}
}
这是resource.groovy
flowHandlerAdapter(FlowHandlerAdapter) {
flowExecutor = ref("flowExecutor");
}
flowHandlerMapping(FlowHandlerMapping) {
flowRegistry = ref("flowRegistry");
}
问题是 为什么我的布局没有被渲染?我错过了什么?
终于找到了这个问题的答案。如果我使用 SitemeshLayoutViewResolver layoutViewResolver
,而不是创建自定义解析器 GroovyPageViewResolver innerGspViewResolver = new GroovyPageViewResolver(groovyPagesTemplateEngine, groovyPageLocator);
,那么我的问题就解决了。所以基本上它必须是这样的。
@Bean
ViewResolver gspViewResolver() {
return jspViewResolver;
}
@Autowired
GrailsViewResolver jspViewResolver
这是示例项目 here,以防有人正在寻找工作示例。
更新
当我完成所有这些后,我遇到了一个非常奇怪的问题。当我 运行 来自 intellij 的应用程序时,应用程序的 webflow 部分工作正常。但是当我使用 gradlew assemble
任务创建 war
时,我总是在应用程序上看到 /error 页面。在日志中,它显示 No mapping found for HTTP request with URI * in DispatcherServlet with name 'grailsDispatcherServlet'
.
显然,我要创建的 bean 不存在。为了解决这个问题,我放弃了基于注释的配置,并将 resources.xml 文件放在 grails-app/conf/spring/
目录中。这解决了 war 的问题。这是我的配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.4.xsd">
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/flows/install-repository.xml" id="installrep/install"/>
</webflow:flow-registry>
<webflow:flow-executor id="flowExecutor" />
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="resolvers"/>
</bean>
<bean id="resolvers" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="jspViewResolver" />
</list>
</constructor-arg>
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
<property name="order" value="0"/>
</bean>
</beans>
要使用 resources.groovy 而不是 applicationContext.xml,您可以执行以下操作:
xmlns([webflow:"http://www.springframework.org/schema/webflow-config"])
webflow.flow-registry(
id:"flowRegistry",
flow-builder-services:"flowBuilderServices"
){
webflow.flow-location(
path:"/WEB-INF/flows/install-repository.xml",
id:"installrep/install"
)
}//eo flow-registry
webflow.flow-executor(id:"flowExecutor")
webflow.flow-builder-services(
id:"flowBuilderServices",
view-factory-creator:"mvcViewFactoryCreator")
mvcViewFactoryCreator(org.springframework.webflow.mvc.builder.MvcViewFactoryCreator){
viewResolvers = ref("resolvers")
}
resolvers(ArrayList, [ ref("jspViewResolver") ])
myFlowHandlerAdapter(org.springframework.webflow.mvc.servlet.FlowHandlerAdapter){
flowExecutor = ref("flowExecutor")
}
myFlowHandlerMapping(org.springframework.webflow.mvc.servlet.FlowHandlerMapping){
flowRegistry = ref("flowRegistry")
order = 0
}