6

私は一連の 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 デコレーター サーブレットの宣言とマッピングが含まれています。

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 サーブレット:

<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 サーブレットを定義しました。

resources.groovy:

beans = {
    sitemeshFreemarkerServlet(ServletRegistrationBean) {
        servlet = bean(FreemarkerDecoratorServlet)
        urlMappings = ["*.ftl"]
        loadOnStartup = 2
    }
}

ただし、grails 3.x アプリケーションは、layouts/main.gsp を使用して gsp ページをレンダリングすることを要求します。decorators.xml が処理されていないようです。私は何が欠けていますか?

4

1 に答える 1

4

醜いハックかもしれませんが、サイトメッシュ処理を grails に重ねることができます。

  • カスタム サイトメッシュ フィルターを Application クラス (または 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;
    }

  • サイトメッシュの設定はデフォルトのものであってはなりません。grails がそれを読み続けるからです。
  • freemarker サーブレットを登録して、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());
    }
}

  • このフィルタでは、新しいサイトメッシュ ファクトリのデコレータ セレクタをオーバーライドする必要があります。これは、デフォルトのものがシングルトン (sic) であり、grails が内部 gsp 処理のために既に登録しているためです。
  • grails がデフォルトの sitemesh factory で gsp を処理できるようにするために、コンテンツ proccesor (initContentProcessor メソッド) をオーバーライドする必要はありません。
  • より多くの機能 (除外されたパターンなど) を取得したい場合は、doFilter メソッド全体をオーバーライドして、新しい contentProcessor を使用する必要があります。contentProcessor.handles(webAppContext)
  • my.sitemesh.xml と decorators.xml を src/main/webapp/WEB-INF に追加します
  • フィルタの初期化でサーブレット コンテキストに grailsApplication を追加したので、ftl テンプレートで使用できます。
  • 一部のレイアウトをスキップしたい場合は、grails の内部レイアウトに環境別の条件を追加します
于 2016-02-09T06:53:48.610 に答える