2014-05-14 13 views
5

Possiedo un'applicazione web MVC Spring che utilizza freemarker come lingua modello. Attualmente sto lavorando sulle modifiche per svuotare la sezione head html invece di buffering dell'intero html e del flushing alla fine. Ho provato a impostare il auto_flush freemarker setting su false e ad usare la direttiva incorporata del freemarker < #flush come di seguito, ma non sembra funzionare.Flussaggio testa HTML con freemarker

common-header.ftl 
<head> 
....... 
</head> 
<#flush> 

page.ftl 
<#include "common-header.ftl" /> 
<body> 
....... 
</body> 

Gradirei il vostro aiuto con questo. Inoltre, secondo lo standard API documentation, autoFlush() sembra funzionare solo per le pagine che non sono composte da istruzioni #include e richiedono più metodi Template.process(). Se è corretto, dovrei scrivere un template processor personalizzato per gestire le sezioni head e body nella mia pagina? Qualsiasi suggerimento sarebbe utile.

Aggiornamento:

Provato utilizzando FreeMarkerView.java come la classe di visualizzazione in quanto utilizza il writer predefinito (PrinterWriter) di HttpServletResponse per elaborare lo scrittore. Anche se PrinterWriter supporta flush() e la direttiva freemarker < #flush> nel mio modello non sembra funzionare.

Provato a estendere la classe FreeMarkerView per avvolgere il PrinterWriter all'interno di un BufferedWriter e che non funziona altrettanto bene.

<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> 
    <property name="suffix"><value>.ftl</value></property> 
    <property name="contentType"><value>text/html; charset=utf-8</value></property> 
    <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> 
    <property name="exposeSpringMacroHelpers"><value>true</value></property> 
</bean> 

Apprezzerei qualsiasi aiuto con questo.

+0

Come si fa a testare questo? –

+0

Aleksandr M @, puoi approfondire? Ho provato distribuendo l'applicazione web e richiedendo le pagine html generate con Freemarker. – soontobeared

+0

"ma quello non sembra funzionare" cosa ti fa pensare che? – Raedwald

risposta

2

<#flush> chiama semplicemente Writer.flush() su Writer assegnato a Template.process. Se, ad esempio, che Writer è un StringWriter, la chiamata flush() non farà nulla, naturalmente. La cosa che passa il Writer a FreeMarker dovrà assicurarsi che quello Writer faccia la cosa giusta quando viene chiamato il suo metodo flush().

auto_flush non è correlato al tuo problema. (Ma hai frainteso i documenti API. auto_flush è sempre supportato.I documenti descrivono il caso quando vuoi impostarlo su false.)

+0

Grazie ddekany @. Sai quale Writer usa Spring [FreeMarkerConfigurer] (http://docs.spring.io/spring/docs/3.2.8.RELEASE/javadoc-api/org/springframework/web/servlet/view/freemarker/FreeMarkerConfigurer.html) uso ? E, se c'è un modo semplice per cambiare lo scrittore in qualcosa come BufferedWriter in modo che l'aggiunta della direttiva invochi il metodo di flush del BufferedWriter? – soontobeared

+0

Non conosco molto Spring MVC. Ma 'FreeMarkerConfigurer' sembra occuparsi solo della costruzione dell'oggetto' Configuration' di FreeMarker, che non influenza ciò che 'Writer' sarà. Un diverso 'Writer' può essere passato ad ogni chiamata' Template.process', quindi non è un'impostazione globale in FreeMarker. – ddekany

+0

Il writer che ho (accessibile tramite org.springframework.web.servlet.view.freemarker.FreeMarkerView) è org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper $ SaveContextPrintWriter che sembra delegare a org.apache.catalina.connector.CoyoteWriter – Goose

1

Non una risposta alla domanda originale ma a un commento @soontobeared. Non sono mai stato informato del tuo commento così dispiaciuto per la risposta in ritardo.

Sto usando una vista bufferizzata durante lo sviluppo in modo da poter catturare varie eccezioni e debug di output, ecc. Ciò consentirà l'accesso al writer. Sto usando Spring 3.2 e FreeMarker 2.3.

BufferedFreeMarkerView.java

package com.example.web; 

import java.io.IOException; 
import java.io.StringWriter; 
import java.io.Writer; 
import java.util.Set; 

import javax.servlet.http.HttpServletResponse; 

import org.springframework.web.servlet.view.freemarker.FreeMarkerView; 

import freemarker.core.InvalidReferenceException; 
import freemarker.template.SimpleHash; 
import freemarker.template.Template; 
import freemarker.template.TemplateException; 

public class BufferedFreeMarkerView extends FreeMarkerView { 

    @Override 
    protected void processTemplate(Template template, SimpleHash model, 
      HttpServletResponse response) throws IOException, TemplateException { 
     StringWriter buffer = new StringWriter(50000); 
     try { 
      template.process(model, buffer); 
     } catch (TemplateException e) { 
      logger.warn(e.getMessage() + "\n" + e.getFTLInstructionStack(), e); 
      throw new RuntimeException(e.getMessage() + "\n" 
        + e.getFTLInstructionStack(), e); 
     } // ommited more catches 

     try (Writer out = response.getWriter()) { 
      out.write(buffer.toString()); 
     } 
    } 

} 

BufferedFreeMarkerViewResolver.java

package com.example.web; 

import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; 

public class BufferedFreeMarkerViewResolver extends FreeMarkerViewResolver { 

    /** 
    * 
    */ 
    public BufferedFreeMarkerViewResolver() { 
     setViewClass(requiredViewClass()); 
    } 

    @SuppressWarnings("rawtypes") 
    @Override 
    protected Class requiredViewClass() { 
     return BufferedFreeMarkerView.class; 
    } 

} 

Dalla primavera contesto dispatcher

<bean id="viewResolver" class="com.example.web.BufferedFreeMarkerViewResolver"> 
    <property name="cache" value="true"/> 
    <property name="prefix" value=""/> 
    <property name="suffix" value=".ftl"/> 
    <property name="allowSessionOverride" value="true"/> 
    <property name="exposeSpringMacroHelpers" value="true"/> 
    <property name="exposeRequestAttributes" value="true"/> 
    <property name="exposeSessionAttributes" value="true"/> 
    <property name="requestContextAttribute" value="rc"/> 
</bean>