在 Grails 3 中使用 Sitemesh
Use of Sitemesh in Grails 3
我正在将一组 grails 2.0.4 应用程序迁移到版本 3.x。所有这些都与许多 java 应用程序一起部署在同一台服务器上。两组 java 和 grails 应用程序都使用 sitemesh 和 freemarker 模板具有共同的外观。
但是使用 grails 3.x 我无法使 commond 装饰工作,应用程序坚持使用 layouts/main.gsp 来呈现我的 gsp。
到目前为止 (grails 2.0.4) 提供通用装饰是相当直接的;每个 grails 应用程序的文件 /WEB-INF/decorators.xml 提供了对适用的 freemarker 模板的引用。 web.xml 包括 sitemesh 过滤器和 freemarker 装饰器 servlet 声明和映射
decorators.xml:
<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/">
<excludes>
<pattern>/ND/*</pattern>
<pattern>/*/ND/*</pattern>
</excludes>
<decorator name="freemarker" page="myftl.ftl">
<pattern>/*</pattern>
</decorator>
</decorators>
来自 web.xml 的 Sitemesh 过滤器和 freemarker servlet:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>sitemesh-freemarker</servlet-name>
<servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>class://</param-value>
</init-param>
<init-param>
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sitemesh-freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
我尝试过的:
- 我已将 decorators.xml 移到 src/main/webapp/WEB-INF
下
- 在 grails 中 3.x sitemesh 过滤器不再存在,所以我删除了 sitemesh.xml
- web.xml 没有使用,所以现在我已经在 spring/resources.groovy:
定义了 freemarker servlet
resources.groovy:
beans = {
sitemeshFreemarkerServlet(ServletRegistrationBean) {
servlet = bean(FreemarkerDecoratorServlet)
urlMappings = ["*.ftl"]
loadOnStartup = 2
}
}
然而,grails 3.x 应用程序坚持使用 layouts/main.gsp 来呈现我的 gsp 页面。 decorators.xml 似乎没有被处理。我错过了什么?
也许是一个丑陋的 hack,但你可以将你的 sitemesh 处理叠加到 grails one:
- 在应用程序 class(或 spring/resources.groovy)中注册自定义站点网过滤器:
@Bean
FilterRegistrationBean sitemeshFilterRegistrationBean() {
FilterRegistrationBean reg=new FilterRegistrationBean()
reg.setFilter(new MySitemeshFilter());
reg.setInitParameters(["configFile":"WEB-INF/my.sitemesh.xml"])
reg.setUrlPatterns(["/*"])
reg.setDispatcherTypes(DispatcherType.REQUEST,DispatcherType.ERROR);
reg.setOrder(0);
return reg;
}
- sitemesh 配置不能是默认配置,因为 grails 继续
正在阅读
- 注册 freemarker servlet 以处理 ftl:
@Bean
ServletRegistrationBean freeMarkerServletRegistrationBean(){
ServletRegistrationBean reg=new ServletRegistrationBean(new
FreemarkerDecoratorServlet(),"*.ftl");
reg.addInitParameter("TemplatePath", "class://");
reg.addInitParameter("default_encoding", "UTF-8");
// etc
return reg;
}
- 添加自定义站点网过滤器:
import com.opensymphony.module.sitemesh.Config;
import com.opensymphony.module.sitemesh.Factory
import com.opensymphony.module.sitemesh.factory.DefaultFactory;
import com.opensymphony.sitemesh.ContentProcessor;
import com.opensymphony.sitemesh.DecoratorSelector;
import com.opensymphony.sitemesh.compatability.DecoratorMapper2DecoratorSelector;
import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext;
import grails.util.Holders;
import javax.servlet.FilterConfig
class MySitemeshFilter extends com.opensymphony.sitemesh.webapp.SiteMeshFilter {
private static final String MY_SITEMESH_FACTORY = "my.sitemesh.factory";
private FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) {
super.init(filterConfig);
filterConfig.getServletContext().setAttribute("grailsApplication", Holders.grailsApplication);
this.filterConfig=filterConfig;
}
protected Factory getFactory(FilterConfig filterConfig) {
Config config=new Config(filterConfig)
Factory f=(Factory)config.getServletContext().getAttribute(MY_SITEMESH_FACTORY);
if (f==null) {
f=new DefaultFactory(config);
config.getServletContext().setAttribute(MY_SITEMESH_FACTORY, f);
}
return f;
}
@Override
protected DecoratorSelector initDecoratorSelector(SiteMeshWebAppContext webAppContext) {
Factory factory = getFactory(filterConfig);
factory.refresh();
return new DecoratorMapper2DecoratorSelector(factory.getDecoratorMapper());
}
}
- 在这个过滤器中,你必须在一个新的 sitemesh 工厂中覆盖装饰器选择器,因为默认的是一个单例(原文如此)并且 grails 已经为它的内部 gsp 处理注册了它
- 您不应该覆盖内容处理器(initContentProcessor 方法),让 grails 使用默认的 sitemesh 工厂处理 gsp
- 如果您想获得更多功能(如排除的模式),您将需要覆盖整个 doFilter 方法以在
contentProcessor.handles(webAppContext)
中使用新的 contentProcessor
- 在 src/main/webapp/WEB-INF
中添加您的 my.sitemesh.xml 和 decorators.xml
- 我在过滤器初始化中将 grailsApplication 添加到 servlet 上下文中,因此您可以在 ftl 模板中使用它
- 如果要跳过某些布局,请在内部 grails 布局中按环境添加条件
我正在将一组 grails 2.0.4 应用程序迁移到版本 3.x。所有这些都与许多 java 应用程序一起部署在同一台服务器上。两组 java 和 grails 应用程序都使用 sitemesh 和 freemarker 模板具有共同的外观。 但是使用 grails 3.x 我无法使 commond 装饰工作,应用程序坚持使用 layouts/main.gsp 来呈现我的 gsp。
到目前为止 (grails 2.0.4) 提供通用装饰是相当直接的;每个 grails 应用程序的文件 /WEB-INF/decorators.xml 提供了对适用的 freemarker 模板的引用。 web.xml 包括 sitemesh 过滤器和 freemarker 装饰器 servlet 声明和映射
decorators.xml:
<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/">
<excludes>
<pattern>/ND/*</pattern>
<pattern>/*/ND/*</pattern>
</excludes>
<decorator name="freemarker" page="myftl.ftl">
<pattern>/*</pattern>
</decorator>
</decorators>
来自 web.xml 的 Sitemesh 过滤器和 freemarker servlet:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>sitemesh-freemarker</servlet-name>
<servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>class://</param-value>
</init-param>
<init-param>
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sitemesh-freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
我尝试过的:
- 我已将 decorators.xml 移到 src/main/webapp/WEB-INF 下
- 在 grails 中 3.x sitemesh 过滤器不再存在,所以我删除了 sitemesh.xml
- web.xml 没有使用,所以现在我已经在 spring/resources.groovy: 定义了 freemarker servlet
resources.groovy:
beans = {
sitemeshFreemarkerServlet(ServletRegistrationBean) {
servlet = bean(FreemarkerDecoratorServlet)
urlMappings = ["*.ftl"]
loadOnStartup = 2
}
}
然而,grails 3.x 应用程序坚持使用 layouts/main.gsp 来呈现我的 gsp 页面。 decorators.xml 似乎没有被处理。我错过了什么?
也许是一个丑陋的 hack,但你可以将你的 sitemesh 处理叠加到 grails one:
- 在应用程序 class(或 spring/resources.groovy)中注册自定义站点网过滤器:
@Bean
FilterRegistrationBean sitemeshFilterRegistrationBean() {
FilterRegistrationBean reg=new FilterRegistrationBean()
reg.setFilter(new MySitemeshFilter());
reg.setInitParameters(["configFile":"WEB-INF/my.sitemesh.xml"])
reg.setUrlPatterns(["/*"])
reg.setDispatcherTypes(DispatcherType.REQUEST,DispatcherType.ERROR);
reg.setOrder(0);
return reg;
}
- sitemesh 配置不能是默认配置,因为 grails 继续 正在阅读
- 注册 freemarker servlet 以处理 ftl:
@Bean
ServletRegistrationBean freeMarkerServletRegistrationBean(){
ServletRegistrationBean reg=new ServletRegistrationBean(new
FreemarkerDecoratorServlet(),"*.ftl");
reg.addInitParameter("TemplatePath", "class://");
reg.addInitParameter("default_encoding", "UTF-8");
// etc
return reg;
}
- 添加自定义站点网过滤器:
import com.opensymphony.module.sitemesh.Config;
import com.opensymphony.module.sitemesh.Factory
import com.opensymphony.module.sitemesh.factory.DefaultFactory;
import com.opensymphony.sitemesh.ContentProcessor;
import com.opensymphony.sitemesh.DecoratorSelector;
import com.opensymphony.sitemesh.compatability.DecoratorMapper2DecoratorSelector;
import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext;
import grails.util.Holders;
import javax.servlet.FilterConfig
class MySitemeshFilter extends com.opensymphony.sitemesh.webapp.SiteMeshFilter {
private static final String MY_SITEMESH_FACTORY = "my.sitemesh.factory";
private FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) {
super.init(filterConfig);
filterConfig.getServletContext().setAttribute("grailsApplication", Holders.grailsApplication);
this.filterConfig=filterConfig;
}
protected Factory getFactory(FilterConfig filterConfig) {
Config config=new Config(filterConfig)
Factory f=(Factory)config.getServletContext().getAttribute(MY_SITEMESH_FACTORY);
if (f==null) {
f=new DefaultFactory(config);
config.getServletContext().setAttribute(MY_SITEMESH_FACTORY, f);
}
return f;
}
@Override
protected DecoratorSelector initDecoratorSelector(SiteMeshWebAppContext webAppContext) {
Factory factory = getFactory(filterConfig);
factory.refresh();
return new DecoratorMapper2DecoratorSelector(factory.getDecoratorMapper());
}
}
- 在这个过滤器中,你必须在一个新的 sitemesh 工厂中覆盖装饰器选择器,因为默认的是一个单例(原文如此)并且 grails 已经为它的内部 gsp 处理注册了它
- 您不应该覆盖内容处理器(initContentProcessor 方法),让 grails 使用默认的 sitemesh 工厂处理 gsp
- 如果您想获得更多功能(如排除的模式),您将需要覆盖整个 doFilter 方法以在
contentProcessor.handles(webAppContext)
中使用新的 contentProcessor
- 在 src/main/webapp/WEB-INF 中添加您的 my.sitemesh.xml 和 decorators.xml
- 我在过滤器初始化中将 grailsApplication 添加到 servlet 上下文中,因此您可以在 ftl 模板中使用它
- 如果要跳过某些布局,请在内部 grails 布局中按环境添加条件