2013-07-22 2 views
3

Я интегрирую struts2, tiles3 и Freemarker (шаблоны из БД). Интеграция в основном выполняется, но рендеринг freemarker представляет собой результат сразу же, вместо того, чтобы вставлять его содержимое в шаблон в ожидаемом месте.Apache-Tiles3 и Freemarker, где результат freemarker обрабатывается из String, вывод визуализации слишком рано

Любые советы о том, как исправить это?

Ожидаемый результат:

<!DOCTYPE html> 
<html> 
    <body> 
     <h1>Template</h1> 
<strong>A bold statement!</strong><div>a message from the Action...</div><div> I came from: the_location</div><div>a message from the Action...</div> 
    </body> 
</html> 

Фактический выход (не отформатирован для удобства чтения, потому что это проблема шаблона, а не HTML вопрос так точность выходных отсчетов):

<strong>A bold statement!</strong><div>a message from the Action...</div><div> I came from: the_location</div> 


<!DOCTYPE html> 
<html> 
    <body> 
     <h1>Template</h1> 

    </body> 
</html> 

tiles-defs.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd"> 
<tiles-definitions> 
    <definition name="test_def2" template="/WEB-INF/template/template.jsp"> 
     <put-attribute name="body" value="the_location" type="db_freemarker"/> 
    </definition> 
</tiles-definitions> 

/WEB-INF/template/template.jsp

<%@taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> 
<%@taglib prefix="s" uri="/struts-tags"%> 
<%@page contentType="text/html" pageEncoding="UTF-8" %> 
<!DOCTYPE html> 
<html> 
    <body> 
     <h1>Template</h1> 
     <tiles:insertAttribute name="body"/> 
    </body> 
</html> 

создал и зарегистрировал DbFreemarkerTilesRenderer с ключом "db_freemarker", это реализация DbFreemarkerTilesRenderer:

package com.quaternion.struts2.result.freemarker; 

import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.tiles.request.Request; 
import org.apache.tiles.request.freemarker.render.FreemarkerRenderer; 
import org.apache.tiles.request.render.CannotRenderException; 
import org.apache.tiles.request.servlet.ServletRequest; 


public class DbFreemarkerTilesRenderer extends FreemarkerRenderer{ 
    public DbFreemarkerTilesRenderer(){ 
     super(null); //Expects a AttributeValueFreemarkerServlet 
    } 

     /** {@inheritDoc} */ 
    @Override 
    public void render(String location, Request request) throws IOException { 
     if (location == null) { 
      throw new CannotRenderException("Cannot dispatch a null path"); 
     } 
     ServletRequest servletRequest = org.apache.tiles.request.servlet.ServletUtil.getServletRequest(request); 
     HttpServletRequest httpRequest = servletRequest.getRequest(); 
     HttpServletResponse httpResponse = servletRequest.getResponse(); 

     DataBaseTemplateLoader dataBaseTemplateLoader = new DataBaseTemplateLoader(); 
     try { 
      dataBaseTemplateLoader.render(location, httpRequest, httpResponse); 
     } catch (Exception ex) { 
      Logger.getLogger(DbFreemarkerTilesRenderer.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 

«DataBaseTemplateLoader» фактически загружает шаблон freemarker из жестко закодированной строки, но он будет загружаться из базы данных после того, как эта проблема будет res olved (см визуализацииметод остальная часть класса входит в контекст, разработчики Struts2 распознает его как тип результата, идея в том, функциональность Freemarker DB могут быть предоставлены непосредственно Struts2 как результат):

package com.quaternion.struts2.result.freemarker; 

import com.opensymphony.xwork2.ActionContext; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.inject.Inject; 
import freemarker.cache.StringTemplateLoader; 
import freemarker.template.Configuration; 
import freemarker.template.Template; 
import freemarker.template.TemplateException; 
import java.util.Map; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.struts2.ServletActionContext; 
import org.apache.struts2.dispatcher.ServletDispatcherResult; 
import org.apache.struts2.views.freemarker.FreemarkerManager; 
import org.apache.struts2.views.util.ContextUtil; 


public class DataBaseTemplateLoader extends ServletDispatcherResult { 

    private static final Logger log = Logger.getLogger(DataBaseTemplateLoader.class.getName()); 
    private String defaultEncoding = "ISO-8859-1"; //TODO: Hardcoded? 
    private FreemarkerManager freemarkerManager; 
    private Configuration configuration; 

    //Inject works if this is a Struts2 component (Result) however 
    //when using this from Tiles, the following is not injected... 
    @Inject 
    public void setFreemarkerManager(FreemarkerManager mgr) { 
     this.freemarkerManager = mgr; 
    } 

    public DataBaseTemplateLoader() { 
     super(); 
    } 

    public DataBaseTemplateLoader(String location) { 
     super(location); //TODO: look up template based on "location" string 
    } 

    protected Configuration getConfiguration() throws TemplateException { 
     if (freemarkerManager == null){ 
      //Force injection 
      freemarkerManager = ActionContext.getContext().getContainer().getInstance(FreemarkerManager.class); 
     } 
     return freemarkerManager.getConfiguration(ServletActionContext.getServletContext()); 
    } 

    @Override 
    public void doExecute(String location, ActionInvocation invocation) throws Exception { 
     HttpServletRequest request = ServletActionContext.getRequest(); 
     HttpServletResponse response = ServletActionContext.getResponse(); 
     render(location, request, response); 
    } 

    public void render(String location, HttpServletRequest request, HttpServletResponse response) throws Exception { 
     //location is String passed from Struts2 action which will formated 
     //in such a way to apply conventions though to view 
     //Format: namespace#action#method 
     //setLocation(location); 

     StringTemplateLoader stringLoader = new StringTemplateLoader(); 

     //BOTH "name" and "source" will be retrieved from the DB 
     String name = "firstTemplate"; 
     String source = "<strong>A bold statement!</strong><div>${action.message}</div><div> I came from: " + location + "</div>"; 

     stringLoader.putTemplate(name, source); 
     // It's possible to add more than one template (they might include each other) 
     // String secondTemplate = "<#include \"greetTemplate\"><@greet/> World!"; 
     // stringLoader.putTemplate("greetTemplate", secondTemplate); 
     freemarker.template.Configuration cfg = getConfiguration(); 
     cfg.setTemplateLoader(stringLoader); 
     Template template = cfg.getTemplate(name); 
     Map map = ContextUtil.getStandardContext(ActionContext.getContext().getValueStack(), request, response); 

     response.setContentType("text/html;charset=" + defaultEncoding); 
     template.process(map, response.getWriter()); 
    } 
} 

Struts2 Действие (не требуется, просто показывает, где "сообщение от действий ..." приходит от:

package com.quaternion.tilesdb.action; 

import com.opensymphony.xwork2.ActionSupport; 
import org.apache.struts2.convention.annotation.ParentPackage; 
import org.apache.struts2.convention.annotation.Result; 

/** 
* Tests Tiles with Freemarker integration, where the freemarker template 
* is parsed from a String, this is to allow later integration with freemarker 
* database templates 
*/ 
@ParentPackage("quaternion-results") 
@Result(type="tiles", location="test_def2") 
public class TilesFtlTest2 extends ActionSupport{ 
    private String message = "a message from the Action..."; 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 
} 
+0

У вас есть SSCCE на GitHub/и т.д.? –

+0

Пока не я. – Quaternion

ответ

2

Я просто хочу закрыть этот вопрос, я ответил, что мне не хватает конфигурации плитки из web.xml (настройка сервлетов Freemarker).

Вот web.xml, который позволяет работать выше:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
    <listener> 
     <listener-class>com.quaternion.struts2.result.freemarker.MoreCompleteAutoloadTilesListener</listener-class> 
     <!--<listener-class>org.apache.tiles.extras.complete.CompleteAutoloadTilesListener</listener-class>--> 
    </listener>  
    <!-- Following is required to enable freemarker(ftl) support--> 
    <servlet> 
     <servlet-name>freemarker</servlet-name> 
     <servlet-class>org.apache.tiles.request.freemarker.servlet.SharedVariableLoaderFreemarkerServlet</servlet-class> 

     <!-- FreemarkerServlet settings: --> 
     <init-param> 
      <param-name>TemplatePath</param-name> 
      <param-value>/WEB-INF/template/</param-value> 
     </init-param> 
     <init-param> 
      <param-name>NoCache</param-name> 
      <param-value>true</param-value> 
     </init-param> 
     <init-param> 
      <param-name>ContentType</param-name> 
      <param-value>text/html</param-value> 
     </init-param> 

     <!-- FreeMarker settings: --> 
     <init-param> 
      <param-name>template_update_delay</param-name> 
      <param-value>0</param-value> <!-- 0 is for development only! Use higher value otherwise. --> 
     </init-param> 
     <init-param> 
      <param-name>default_encoding</param-name> 
      <param-value>ISO-8859-1</param-value> 
     </init-param> 
     <init-param> 
      <param-name>number_format</param-name> 
      <param-value>0.##########</param-value> 
     </init-param> 
     <init-param> 
      <param-name>org.apache.tiles.request.freemarker.CUSTOM_SHARED_VARIABLE_FACTORIES</param-name> 
      <param-value>tiles,org.apache.tiles.freemarker.TilesSharedVariableFactory</param-value> 
     </init-param> 
     <load-on-startup>5</load-on-startup> 
    </servlet> 
    <filter> 
     <filter-name>struts2</filter-name> 
     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>struts2</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <welcome-file-list> 
     <welcome-file>/index.action</welcome-file> 
    </welcome-file-list> 
</web-app> 

 Смежные вопросы

  • Нет связанных вопросов^_^