2016-10-24 124 views
1

我有一個.ftl文件用於通過RESTful端點顯示它的資源,我還希望通過電子郵件將此表示發送給用戶。 Dropwizard使用Views做了一些神奇的事情,允許將填充後的模板主體返回到我的REST端點(我假定爲String或者類似於StringBuilder的其他粉絲)。我可以使用Freemarker從Dropwizard View創建電子郵件嗎?

有沒有辦法在不使用剩餘客戶端的情況下請求View的正文?我不想讓我的電子郵件表示依賴於REST客戶端中使用的HTML,因此沒有建議將郵件路由到打到端點的內容。

從看dropwizard source,看來我需要從某處獲取ViewRenderer,可能通過使用ServiceLoader.load() - 因爲這是如何ViewBundle取得複印件(如果你不提供任何)。

+0

你需要你的觀點被填充當你把它發送給你的客戶呢? – pandaadb

+0

是的,這將是想法,我會通過我的'資源'類的視圖,它會填充到freemarker模板,並通過我回到某種'Outstream'(通過看起來的dropwizard源代碼) – Rossiar

+0

這是完全正確:)不應該有需要服務發現,但只需調用構造函數並創建您的viewmaker並讓它填充它 – pandaadb

回答

3

正如評論中指出的那樣,羅西亞是完全正確的。

達到此目的的方法是使用DW也在使用的相同ViewRenderer。人們不必使用ServiceLocator模式,因爲他們所做的只是調用構造函數。

一個小例子:

public class MyView extends View { 

    private TestPerson person; 

    protected MyView(TestPerson person) { 
     super("TestView.ftl"); 
     this.person = person; 
    } 

    public TestPerson getPerson() { 
     return person; 
    } 

    public static class TestPerson { 

     public String getName() { 
      return "PandaaDb"; 
     } 

    } 
} 

這是我們想渲染視圖類。注意:Freemaker希望這些方法是公開的,否則它將拒絕訪問它們。

相應的FTL文件:

<#-- @ftlvariable name="" type="viewTest.Two.MyView" --> 
<html> 
    <body> 
     <h1>Hello, ${person.name?html}</h1> 
    </body> 
</html> 

然後,在我的主,我們可以這樣做:

public class ViewTestMain { 

    public static void main(String[] args) throws UnsupportedEncodingException { 
     FreemarkerViewRenderer render = new FreemarkerViewRenderer(); 

     TestPerson p = new TestPerson(); 
     MyView v = new MyView(p); 

     ByteArrayOutputStream st = new ByteArrayOutputStream(); 

     try { 
      render.render(v, Locale.getDefault(), st); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     String string = st.toString("UTF-8"); 
     System.out.println(string); 
    } 
} 

,或者,我們可以重用DW奠定了我們通過查詢模式服務定位器並檢查每個ViewRenderer是否適用。

public class ViewTestMain { 

    public static void main(String[] args) throws UnsupportedEncodingException { 
     ServiceLoader<ViewRenderer> load = ServiceLoader.load(ViewRenderer.class); 
     TestPerson p = new TestPerson(); 
     MyView v = new MyView(p); 

     ByteArrayOutputStream st = new ByteArrayOutputStream(); 

     ViewRenderer r = null; 
     for(ViewRenderer vr : load) { 
      if(vr.isRenderable(v)) { 
       r = vr; 
      } 
     } 

     try { 
      r.render(v, Locale.getDefault(), st); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     String string = st.toString("UTF-8"); 
     System.out.println(string); 
    } 
} 

請注意,您可以通過簡單地將實現添加到服務來添加自己的ServiceRenderer。這是通過將與ServiceRender接口名稱(完全限定)的文件進行到

src/main/resources/META-INF/services 

,然後加入完全合格的實現名到該文件。這將使其可發現。

,它將打印:

<html> 
    <body> 
     <h1>Hello, PandaaDb</h1> 
    </body> 
</html> 

現在,我假設你已經從球衣層的DAO /服務層分裂。在這種情況下,您可以編寫一個簡單訪問相同模型對象的客戶端,以與DW通常一樣的方式實例化視圖,並簡單地通過渲染來運行它們。

希望幫助,

阿圖爾

+0

嗨Artur,感謝您的高品質答案 - 有沒有辦法通過實例化自己到'FreemarkerViewRenderer'綁定?使用'ViewBundle'中的渲染器的優點是它在我所關心的範圍之外被實例化。在你的例子中,如果我想將我的模板引擎更改爲鬍鬚,那麼我將不得不更改此代碼,這並不理想。 – Rossiar

+0

@Rossiar看到更新,我也在那裏添加了服務加載器的方法。對不起,我以爲你想繞過服務加載器:) – pandaadb

+0

乾杯!我應該能夠將這些擔憂分離出來並制定一個工作解決方案。 – Rossiar

相關問題